HEX
Server: LiteSpeed
System: Linux houston.panomity.com 6.8.0-100-generic #100-Ubuntu SMP PREEMPT_DYNAMIC Tue Jan 13 16:40:06 UTC 2026 x86_64
User: nudepix (1011)
PHP: 7.4.33
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Upload Files
File: //workspace/rollout/frontend-route.ts.expected
import { NextRequest } from "next/server";

const RAW_INTERNAL_API_URL = process.env.INTERNAL_API_URL ?? "";
const INTERNAL_API_URL =
  RAW_INTERNAL_API_URL.trim().replace(/\/+$/, "") || "http://127.0.0.1:3411";
const LOCAL_MODE = (process.env.NEXT_PUBLIC_AUTH_MODE ?? "").trim() === "local";
const CONFIGURED_LOCAL_TOKEN = (
  process.env.NEXT_PUBLIC_LOCAL_AUTH_TOKEN ?? process.env.LOCAL_AUTH_TOKEN ?? ""
)
  .trim();

const HOP_BY_HOP_REQUEST_HEADERS = new Set([
  "connection",
  "keep-alive",
  "proxy-authenticate",
  "proxy-authorization",
  "te",
  "trailer",
  "transfer-encoding",
  "upgrade",
  "host",
]);

const HOP_BY_HOP_RESPONSE_HEADERS = new Set([
  "connection",
  "keep-alive",
  "proxy-authenticate",
  "proxy-authorization",
  "te",
  "trailer",
  "transfer-encoding",
  "upgrade",
]);

function targetUrlFrom(req: NextRequest, path: string[] | undefined): string {
  const joined = (path ?? []).join("/");
  const suffix = joined ? `/${joined}` : "";
  const search = req.nextUrl.search || "";
  return `${INTERNAL_API_URL}/api${suffix}${search}`;
}

function prepareRequestHeaders(req: NextRequest): Headers {
  const headers = new Headers(req.headers);

  for (const name of HOP_BY_HOP_REQUEST_HEADERS) {
    headers.delete(name);
  }

  const overrideToken = (headers.get("x-mc-local-token") ?? "").trim();
  headers.delete("x-mc-local-token");

  if (LOCAL_MODE) {
    if (overrideToken) {
      headers.set("authorization", `Bearer ${overrideToken}`);
    } else if (!headers.has("authorization")) {
      const effective = CONFIGURED_LOCAL_TOKEN;
      if (!effective) {
        throw new Error(
          "Local auth mode is enabled but no token is configured in frontend environment.",
        );
      }
      headers.set("authorization", `Bearer ${effective}`);
    }
  }

  return headers;
}

function prepareResponseHeaders(upstream: Headers): Headers {
  const headers = new Headers(upstream);
  for (const name of HOP_BY_HOP_RESPONSE_HEADERS) {
    headers.delete(name);
  }
  return headers;
}

async function proxy(req: NextRequest, path: string[] | undefined): Promise<Response> {
  let requestHeaders: Headers;
  try {
    requestHeaders = prepareRequestHeaders(req);
  } catch (error) {
    const message = error instanceof Error ? error.message : "Proxy auth setup failed";
    return Response.json({ detail: message }, { status: 500 });
  }

  const method = req.method.toUpperCase();
  const hasBody = method !== "GET" && method !== "HEAD";
  const body = hasBody ? await req.arrayBuffer() : undefined;

  const upstream = await fetch(targetUrlFrom(req, path), {
    method,
    headers: requestHeaders,
    body,
    redirect: "manual",
    cache: "no-store",
  });

  return new Response(upstream.body, {
    status: upstream.status,
    statusText: upstream.statusText,
    headers: prepareResponseHeaders(upstream.headers),
  });
}

type RouteContext = {
  params: Promise<{
    path: string[];
  }>;
};

export async function GET(req: NextRequest, ctx: RouteContext): Promise<Response> {
  const { path } = await ctx.params;
  return proxy(req, path);
}

export async function POST(req: NextRequest, ctx: RouteContext): Promise<Response> {
  const { path } = await ctx.params;
  return proxy(req, path);
}

export async function PUT(req: NextRequest, ctx: RouteContext): Promise<Response> {
  const { path } = await ctx.params;
  return proxy(req, path);
}

export async function PATCH(req: NextRequest, ctx: RouteContext): Promise<Response> {
  const { path } = await ctx.params;
  return proxy(req, path);
}

export async function DELETE(req: NextRequest, ctx: RouteContext): Promise<Response> {
  const { path } = await ctx.params;
  return proxy(req, path);
}

export async function OPTIONS(req: NextRequest, ctx: RouteContext): Promise<Response> {
  const { path } = await ctx.params;
  return proxy(req, path);
}