| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| import { NextRequest } from 'next/server' |
| import { rateLimit, getRateLimitHeaders } from '@/lib/security/rateLimiter' |
| import { createSecureResponse, addSecurityHeaders } from '@/lib/security/headers' |
| import { getInferenceUrl } from '@/lib/server/inferenceUrl' |
|
|
| const INFERENCE_TIMEOUT_MS = 30_000 |
|
|
| function isAuthorized(request: NextRequest): boolean { |
| const expected = process.env.INFERENCE_PROXY_TOKEN |
| if (!expected) return false |
| return request.headers.get('x-inference-proxy-token') === expected |
| } |
|
|
| export async function POST(request: NextRequest) { |
| const rateLimitResponse = rateLimit(request, '/api/inference/predict') |
| if (rateLimitResponse) { |
| return addSecurityHeaders(rateLimitResponse) |
| } |
|
|
| if (!isAuthorized(request)) { |
| return createSecureResponse({ error: 'Unauthorized' }, 401) |
| } |
|
|
| let inferenceUrl: string |
| try { |
| inferenceUrl = getInferenceUrl() |
| } catch (error) { |
| console.error('Inference proxy: service misconfigured:', error) |
| return createSecureResponse({ error: 'Prediction service is not configured.' }, 503) |
| } |
|
|
| const formData = await request.formData() |
|
|
| let upstream: Response |
| try { |
| upstream = await fetch(`${inferenceUrl}/predict`, { |
| method: 'POST', |
| body: formData, |
| signal: AbortSignal.timeout(INFERENCE_TIMEOUT_MS), |
| }) |
| } catch (error) { |
| console.error('Inference proxy: upstream unreachable:', error) |
| return createSecureResponse( |
| { error: 'Prediction service unavailable. Please try again shortly.' }, |
| 503 |
| ) |
| } |
|
|
| let result: any |
| try { |
| result = await upstream.json() |
| } catch { |
| console.error('Inference proxy: upstream returned non-JSON, status:', upstream.status) |
| return createSecureResponse({ error: 'Prediction failed. Please try again later.' }, 500) |
| } |
|
|
| const response = createSecureResponse(result, upstream.status) |
| const rateLimitHeaders = getRateLimitHeaders(request, '/api/inference/predict') |
| Object.entries(rateLimitHeaders).forEach(([key, value]) => { |
| response.headers.set(key, value) |
| }) |
| return response |
| } |
|
|