/** * The origin a visitor used, as the reverse proxy in front of this app reports * it. Absolute URLs — `canonical`, `hreflang`, the sitemap, `og:image` — need * one, and this app has no configured address of its own: it answers on * whichever domain the proxy sends it. */ export type HeaderBag = Record; export function originFromHeaders( headers: HeaderBag | undefined, ): string | null { if (!headers) { return null; } const first = (value: string | string[] | undefined) => (Array.isArray(value) ? value[0] : value)?.split(',')[0]?.trim(); const host = first(headers['x-forwarded-host']) ?? first(headers['host']); // Behind the proxy the header is always there; without one this is a // developer's own machine, which does not speak TLS. const protocol = first(headers['x-forwarded-proto']) ?? (/^(localhost|127\.)/.test(host ?? '') ? 'http' : 'https'); return host ? `${protocol}://${host}` : null; }