From cecfcfb6206a1d1fa66ada3ba0c2da193f15efd1 Mon Sep 17 00:00:00 2001 From: TheMaddax Date: Tue, 28 Oct 2025 08:01:22 -0600 Subject: [PATCH] Add Next.js API route proxy to handle client-side API requests to backend --- frontend/src/app/api/[...path]/route.ts | 87 +++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 frontend/src/app/api/[...path]/route.ts diff --git a/frontend/src/app/api/[...path]/route.ts b/frontend/src/app/api/[...path]/route.ts new file mode 100644 index 00000000..e72a6b06 --- /dev/null +++ b/frontend/src/app/api/[...path]/route.ts @@ -0,0 +1,87 @@ +import { NextRequest, NextResponse } from 'next/server'; + +// This catch-all API route proxies all /api/* requests to the backend +export async function GET( + request: NextRequest, + { params }: { params: { path: string[] } } +) { + return proxyToBackend(request, params.path); +} + +export async function POST( + request: NextRequest, + { params }: { params: { path: string[] } } +) { + return proxyToBackend(request, params.path); +} + +export async function PUT( + request: NextRequest, + { params }: { params: { path: string[] } } +) { + return proxyToBackend(request, params.path); +} + +export async function DELETE( + request: NextRequest, + { params }: { params: { path: string[] } } +) { + return proxyToBackend(request, params.path); +} + +async function proxyToBackend(request: NextRequest, pathSegments: string[]) { + const path = pathSegments.join('/'); + const backendUrl = `http://backend:3001/api/${path}`; + + // Get the search params from the original request + const searchParams = request.nextUrl.searchParams.toString(); + const url = searchParams ? `${backendUrl}?${searchParams}` : backendUrl; + + try { + // Forward the request to the backend + const headers: HeadersInit = {}; + + // Copy relevant headers + request.headers.forEach((value, key) => { + if (!key.startsWith('host') && !key.startsWith('connection')) { + headers[key] = value; + } + }); + + const options: RequestInit = { + method: request.method, + headers, + }; + + // Add body for POST, PUT, PATCH requests + if (['POST', 'PUT', 'PATCH'].includes(request.method)) { + const contentType = request.headers.get('content-type'); + if (contentType?.includes('application/json')) { + options.body = JSON.stringify(await request.json()); + } else if (contentType?.includes('multipart/form-data')) { + options.body = await request.formData(); + } else { + options.body = await request.text(); + } + } + + const response = await fetch(url, options); + + // Get response body + const data = await response.text(); + + // Return response with same status and headers + return new NextResponse(data, { + status: response.status, + headers: { + 'Content-Type': response.headers.get('content-type') || 'application/json', + }, + }); + } catch (error) { + console.error('Proxy error:', error); + return NextResponse.json( + { success: false, message: 'Failed to connect to backend' }, + { status: 500 } + ); + } +}