import { getCanonicalHostRedirectUrl, getHostAwareInternalUrlPath, getHostRoutingContextFromRequest } from "../apps/web/app/utils/app/HostRouting.server"; export type HostRoutingRuntimeDecision = | { type: "redirect"; status: 308; location: string } | { type: "reject"; status: 404 } | { type: "dispatch"; target: "api" | "web"; request: Request }; const internalWebApiProxyHeader = "x-toolctrl-internal-web-api-proxy"; export function getHostRoutingRuntimeDecision(request: Request): HostRoutingRuntimeDecision { const context = getHostRoutingContextFromRequest(request); if (isInternalWebApiProxyRequest(request, context)) { const requestUrl = new URL(request.url); const rewrittenRequest = rewriteRequestUrl(request, `${requestUrl.pathname}${requestUrl.search}${requestUrl.hash}`); return { type: "dispatch", target: "web", request: rewrittenRequest, }; } if (isRemovedLegacyRoute(request, context)) { return { type: "reject", status: 404, }; } const canonicalRedirectUrl = getCanonicalHostRedirectUrl(request); if (canonicalRedirectUrl) { return { type: "redirect", status: 308, location: canonicalRedirectUrl, }; } const rewrittenRequest = rewriteRequestUrl(request, getRuntimeInternalUrlPath(request, context)); return { type: "dispatch", target: context === "api" ? "api" : "web", request: rewrittenRequest, }; } function isInternalWebApiProxyRequest(request: Request, context: ReturnType) { if (context !== "app" || request.headers.get(internalWebApiProxyHeader) !== "1") { return false; } const pathname = new URL(request.url).pathname; return pathname === "/internal/api/usage" || pathname === "/internal/api/stripe.webhooks" || pathname.startsWith("/internal/api/workflows/"); } function isRemovedLegacyRoute(request: Request, context: ReturnType) { const pathname = new URL(request.url).pathname.replace(/\/+$/g, "") || "/"; const isLegacyApiV1Route = pathname === "/api/v1" || pathname.startsWith("/api/v1/"); const isAdminApiSectionRoute = context === "admin" && (pathname === "/api" || pathname.startsWith("/api/")) && !isLegacyApiV1Route; return ( pathname === "/app" || pathname.startsWith("/app/") || pathname === "/admin" || pathname.startsWith("/admin/") || (!isAdminApiSectionRoute && (pathname === "/api" || (pathname.startsWith("/api/") && !isLegacyApiV1Route))) ); } function getRuntimeInternalUrlPath(request: Request, context: ReturnType) { if (context === "app") { const url = new URL(request.url); return `${url.pathname}${url.search}${url.hash}`; } return getHostAwareInternalUrlPath(request); } function rewriteRequestUrl(request: Request, internalUrlPath: string) { const url = new URL(request.url); url.pathname = "/"; url.search = ""; url.hash = ""; const rewrittenUrl = new URL(internalUrlPath, url); return new Request(rewrittenUrl, request); }