fix: use runtime BACKEND_URL for proxying (#411)

* fix: use runtime BACKEND_URL for proxying

Fixes #400

* chore: run formatter
This commit is contained in:
Abhishek 2026-06-03 18:47:04 +05:30 committed by GitHub
parent acc2ef9e96
commit cdb27c1d4f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 130 additions and 17 deletions

View file

@ -0,0 +1,104 @@
import { NextRequest, NextResponse } from "next/server";
import { getServerBackendUrl } from "@/lib/apiClient";
export const dynamic = "force-dynamic";
export const runtime = "nodejs";
const HOP_BY_HOP_HEADERS = [
"connection",
"keep-alive",
"proxy-authenticate",
"proxy-authorization",
"te",
"trailer",
"transfer-encoding",
"upgrade",
];
function trimTrailingSlash(url: string) {
return url.endsWith("/") ? url.slice(0, -1) : url;
}
function buildBackendUrl(request: NextRequest) {
const backendUrl = trimTrailingSlash(getServerBackendUrl());
return `${backendUrl}${request.nextUrl.pathname}${request.nextUrl.search}`;
}
function createRequestHeaders(request: NextRequest) {
const headers = new Headers(request.headers);
for (const header of HOP_BY_HOP_HEADERS) {
headers.delete(header);
}
headers.delete("accept-encoding");
headers.delete("content-length");
headers.delete("host");
return headers;
}
function createResponseHeaders(response: Response) {
const headers = new Headers(response.headers);
const setCookies = response.headers.getSetCookie();
for (const header of HOP_BY_HOP_HEADERS) {
headers.delete(header);
}
headers.delete("content-encoding");
headers.delete("content-length");
headers.delete("set-cookie");
for (const cookie of setCookies) {
headers.append("set-cookie", cookie);
}
return headers;
}
async function getRequestBody(request: NextRequest) {
if (request.method === "GET" || request.method === "HEAD") {
return undefined;
}
return request.arrayBuffer();
}
async function proxyRequest(request: NextRequest) {
const backendUrl = buildBackendUrl(request);
try {
const response = await fetch(backendUrl, {
method: request.method,
headers: createRequestHeaders(request),
body: await getRequestBody(request),
cache: "no-store",
});
return new Response(request.method === "HEAD" ? null : response.body, {
status: response.status,
statusText: response.statusText,
headers: createResponseHeaders(response),
});
} catch (error) {
const message =
error instanceof Error ? error.message : "Unknown backend proxy error";
return NextResponse.json(
{
detail: `Backend request failed while proxying to ${backendUrl}: ${message}`,
},
{ status: 502 },
);
}
}
export const GET = proxyRequest;
export const POST = proxyRequest;
export const PUT = proxyRequest;
export const PATCH = proxyRequest;
export const DELETE = proxyRequest;
export const OPTIONS = proxyRequest;
export const HEAD = proxyRequest;

View file

@ -1,5 +1,7 @@
import "server-only";
import { getServerBackendUrl } from "@/lib/apiClient";
let cachedAuthProvider: string | null = null;
/**
@ -12,7 +14,7 @@ export async function getAuthProvider(): Promise<string> {
}
try {
const backendUrl = process.env.BACKEND_URL || "http://localhost:8000";
const backendUrl = getServerBackendUrl();
const res = await fetch(`${backendUrl}/api/v1/health`, {
next: { revalidate: 300 },
});

View file

@ -1,6 +1,8 @@
import type { NextRequest } from 'next/server';
import { NextResponse } from 'next/server';
import { getServerBackendUrl } from '@/lib/apiClient';
const OSS_TOKEN_COOKIE = 'dograh_auth_token';
// Paths that don't require authentication in OSS mode
@ -14,7 +16,7 @@ async function fetchAuthProvider(): Promise<string> {
}
try {
const backendUrl = process.env.BACKEND_URL || 'http://localhost:8000';
const backendUrl = getServerBackendUrl();
const res = await fetch(`${backendUrl}/api/v1/health`);
if (res.ok) {
const data = await res.json();