23 lines · 1.3 KB · TypeScript
RawDownload
// The origin the BROWSER sees for a document request — what origin-derived UI// (the connect card's MCP URL, the API client's base) must be built from.//// On Cloudflare `request.url` already carries the external `https://` origin,// so this is a no-op there. Behind a TLS-terminating reverse proxy that// forwards plain HTTP upstream — `tailscale serve` for the dev-share workflow,// or an nginx/Caddy front — `request.url` is `http://` while the browser is on// `https://`; honoring the proxy's `X-Forwarded-Proto`/`-Host` recovers the// real origin (otherwise the HTTPS page would seed an `http://` API base and// the browser blocks it as mixed content).//// Trusting these headers is safe: the result only shapes the origin rendered// back to that same requester, never a cross-tenant decision (org access is// enforced server-side regardless of the URL the client was handed).//// Pure (no `cloudflare:workers`) so it unit-tests without the worker runtime.export const browserOriginFromRequest = (request: Request): string => {  const url = new URL(request.url);  const proto = request.headers.get("x-forwarded-proto")?.split(",")[0]?.trim();  const host = request.headers.get("x-forwarded-host")?.split(",")[0]?.trim();  if (!proto && !host) return url.origin;  return `${proto || url.protocol.replace(":", "")}://${host || url.host}`;};