From 0d16a798128282b08f67fb8649e7ea6b1ea7f868 Mon Sep 17 00:00:00 2001 From: MaryemWannes Date: Wed, 31 Dec 2025 15:04:25 +0100 Subject: [PATCH] switch cert backend call to server-side --- src/app/api/cert-backend/[...path]/route.ts | 63 +++++++++++++++++++++ src/services/api-client.ts | 7 +-- 2 files changed, 66 insertions(+), 4 deletions(-) create mode 100644 src/app/api/cert-backend/[...path]/route.ts diff --git a/src/app/api/cert-backend/[...path]/route.ts b/src/app/api/cert-backend/[...path]/route.ts new file mode 100644 index 0000000..316750c --- /dev/null +++ b/src/app/api/cert-backend/[...path]/route.ts @@ -0,0 +1,63 @@ +// src/app/api/cert-backend/[...path]/route.ts +import type { NextRequest } from "next/server"; + +const API_BASE_URL = process.env.CERT_BACKEND_API_URL; + +type RouteParams = { path?: string[] }; +type RouteContext = { params: Promise }; + +async function proxyRequest(req: Request, params: RouteParams) { + if (!API_BASE_URL) { + return new Response("Missing CERT_BACKEND_API_URL", { status: 500 }); + } + + const incomingUrl = new URL(req.url); + const baseUrl = API_BASE_URL.replace(/\/+$/, ""); + const path = (params.path ?? []).join("/"); + const targetUrl = `${baseUrl}${path ? `/${path}` : ""}${incomingUrl.search}`; + + const headers = new Headers(req.headers); + headers.delete("host"); + headers.delete("content-length"); + + const init: RequestInit = { + method: req.method, + headers, + cache: "no-store", + }; + + if (req.method !== "GET" && req.method !== "HEAD") { + init.body = await req.arrayBuffer(); + } + + const res = await fetch(targetUrl, init); + + const resHeaders = new Headers(res.headers); + resHeaders.delete("content-encoding"); + + return new Response(await res.arrayBuffer(), { + status: res.status, + headers: resHeaders, + }); +} + +export async function GET(req: NextRequest, ctx: RouteContext) { + const params = await ctx.params; + return proxyRequest(req, params); +} +export async function POST(req: NextRequest, ctx: RouteContext) { + const params = await ctx.params; + return proxyRequest(req, params); +} +export async function PUT(req: NextRequest, ctx: RouteContext) { + const params = await ctx.params; + return proxyRequest(req, params); +} +export async function PATCH(req: NextRequest, ctx: RouteContext) { + const params = await ctx.params; + return proxyRequest(req, params); +} +export async function DELETE(req: NextRequest, ctx: RouteContext) { + const params = await ctx.params; + return proxyRequest(req, params); +} diff --git a/src/services/api-client.ts b/src/services/api-client.ts index 49ae74c..0084603 100644 --- a/src/services/api-client.ts +++ b/src/services/api-client.ts @@ -7,11 +7,10 @@ import { setTokens, } from "@/lib/shared-auth"; -// Backends reading bearers live on CERT_API; tokens are minted by onboarding app. -const API_BASE_URL = - process.env.NEXT_PUBLIC_CERT_API_URL ?? "http://localhost:5000"; +// Proxy through Next.js so the real backend URL stays server-side. +const API_BASE_URL = "/api/cert-backend"; const AUTH_APP_BASE_URL = - process.env.NEXT_PUBLIC_AUTH_APP_URL ?? "http://localhost:3000"; + process.env.NEXT_PUBLIC_AUTH_APP_URL; const REFRESH_ENDPOINT = `${AUTH_APP_BASE_URL}/api/auth/refresh-token`; // Deduplicate concurrent refreshes so only one network call runs at a time.