77 lines · 3.7 KB · TypeScript
RawDownload
// Shared resolution of a host's PUBLIC ORIGIN — the pinned base URL every host// uses to build absolute outbound links (OAuth redirect_uri, MCP OAuth metadata,// connect/approval URLs, email links). One implementation so the hosts don't// drift (selfhost had the platform-detect chain; cloud/cloudflare did not).//// SECURITY: this is for SERVER-SIDE OUTBOUND urls, so the origin must come from// a TRUSTED source — an operator-set env var, or a platform-injected deploy-time// var — NEVER from the request `Host`/`X-Forwarded-Host` (host-header injection// would let an attacker poison those links). The request origin may still be// used for CSRF/origin validation and client-side display; that is each host's// concern, not this module's. /** A read-only environment record (process.env, or a Worker `env` binding). */export type EnvRecord = Record<string, string | undefined>; /** * The public origin a platform-as-a-service injects for this deployment, e.g. * Railway's `RAILWAY_PUBLIC_DOMAIN`. Ordering mirrors `@t3-oss/env-core`'s * `getPlatformOrigin` preset (MIT) — all platform-SET (not client-set) values, * so building absolute URLs from them is safe. Returns an origin (`https://host`, * no trailing slash) or undefined. The generic `PUBLIC_URL`/`APP_URL` from that * preset are deliberately omitted: `PUBLIC_URL` is a *path* in some toolchains * (CRA), not an origin. Cloudflare Workers receive none of these, so it returns * undefined there — expected; the Worker falls back to its own request origin. */export const getPlatformOrigin = (env: EnvRecord): string | undefined => {  const host =    env.RAILWAY_PUBLIC_DOMAIN ??    env.RENDER_EXTERNAL_HOSTNAME ??    env.VERCEL_PROJECT_PRODUCTION_URL ??    env.VERCEL_URL ??    env.HEROKU_APP_DEFAULT_DOMAIN_NAME ??    env.WEBSITE_HOSTNAME ?? // Azure App Service    env.WEBSITE_DEFAULT_HOSTNAME ??    (env.FLY_APP_NAME ? `${env.FLY_APP_NAME}.fly.dev` : undefined) ??    (env.SITE_NAME ? `${env.SITE_NAME}.netlify.app` : undefined);  const url =    env.RENDER_EXTERNAL_URL ??    env.DEPLOY_PRIME_URL ?? // Netlify (deploy/branch previews)    env.URL ?? // Netlify (primary site URL)    env.CF_PAGES_URL ??    (host ? `https://${host}` : undefined);  return url?.replace(/\/+$/, "");}; /** * Resolve a deployment's pinned public origin: an explicit operator-set value * wins, else a platform-injected origin, else undefined (the caller supplies its * own fallback — a `localhost:PORT` for a Node host, a production constant or the * per-request origin for a Worker — and decides whether to warn). */export const resolvePublicOrigin = (options: {  readonly explicit?: string | undefined;  readonly env: EnvRecord;}): string | undefined => {  const explicit = options.explicit?.trim();  if (explicit) return explicit;  return getPlatformOrigin(options.env);}; /** * True unless this is explicitly local dev or a test run. A staging/demo deploy * often leaves `NODE_ENV` unset, and silently using a localhost fallback there is * the footgun we want surfaced — so warn by default. */export const shouldWarnMissingPublicOrigin = (nodeEnv: string | undefined): boolean =>  nodeEnv !== "development" && nodeEnv !== "test"; /** The one-time warning shown when a host falls back for its public origin. */export const missingPublicOriginWarning = (options: {  readonly varName: string;  readonly fallback: string;}): string =>  `[executor] ${options.varName} is not set and no platform origin was detected; ` +  `falling back to ${options.fallback}. OAuth redirects, MCP metadata, and connect ` +  `links will use this — set ${options.varName} to your public origin ` +  `(e.g. https://your-instance.example.com).`;