import { headers } from "next/headers"; import { getEnv } from "@/lib/env"; function getFirstHeaderValue(value: string | null) { return value?.split(",")[0]?.trim() || null; } function sanitizeProto(value: string | null) { const candidate = getFirstHeaderValue(value)?.toLowerCase(); if (candidate === "http" || candidate === "https") { return candidate; } return null; } function sanitizeHost(value: string | null) { const candidate = getFirstHeaderValue(value)?.replace(/^"|"$/g, ""); if (!candidate) { return null; } if (candidate.includes("/") || /\s/.test(candidate)) { return null; } return candidate; } function parseForwardedHeader(value: string | null) { const firstEntry = getFirstHeaderValue(value); if (!firstEntry) { return { host: null, proto: null, }; } let host: string | null = null; let proto: "http" | "https" | null = null; for (const segment of firstEntry.split(";")) { const [rawKey, ...rest] = segment.split("="); const key = rawKey?.trim().toLowerCase(); const rawValue = rest.join("=").trim(); if (!key || !rawValue) { continue; } if (key === "host") { host = sanitizeHost(rawValue) || host; } else if (key === "proto") { proto = sanitizeProto(rawValue) || proto; } } return { host, proto }; } function buildOriginFromParts( host: string | null, proto: "http" | "https" | null, fallback: string, ) { if (!host) { return fallback; } return `${proto || "http"}://${host}`; } export async function getRequestOrigin() { const headerList = await headers(); const envOrigin = getEnv().APP_URL; const forwarded = parseForwardedHeader(headerList.get("forwarded")); const host = sanitizeHost(headerList.get("x-forwarded-host")) || forwarded.host || sanitizeHost(headerList.get("host")); const proto = sanitizeProto(headerList.get("x-forwarded-proto")) || forwarded.proto; return buildOriginFromParts(host, proto, envOrigin); } export function getOriginFromRequest(request: Request) { const url = new URL(request.url); const forwarded = parseForwardedHeader(request.headers.get("forwarded")); const host = sanitizeHost(request.headers.get("x-forwarded-host")) || forwarded.host || sanitizeHost(request.headers.get("host")) || url.host; const proto = sanitizeProto(request.headers.get("x-forwarded-proto")) || forwarded.proto || sanitizeProto(url.protocol.replace(/:$/, "")); return buildOriginFromParts(host, proto, getEnv().APP_URL); }