import type { IncomingHttpHeaders, IncomingMessage } from 'node:http' /** Paths Vite itself serves (HMR client, source modules, deps). */ export const isViteOwned = (url: string) => /^\/(@|src\/|node_modules\/|__|mock\/|test\/)/.test(url) /** A navigation to a page we should fetch + inject, as opposed to an asset/API call. */ export function isPageRequest(req: IncomingMessage): boolean { const url = req.url ?? '/' if (req.method !== 'GET' || isViteOwned(url)) return false if (/^\/(api|editor|assets|js|css|fonts|static)(\/|$)/.test(url)) return false if (/\.[a-z0-9]{2,5}($|\?)/i.test(url.split('?')[0])) return false // has a file extension return String(req.headers.accept ?? '').includes('text/html') } export interface Auth { token?: string apiKey?: string cookie?: string } const hasPreviewCookie = (cookie?: string) => /(?:^|;\s*)cms_preview=1/.test(cookie ?? '') /** Headers for an upstream request: browser cookies + configured credentials + preview flag. */ export function upstreamHeaders( incoming: IncomingHttpHeaders, auth: Auth, opts: { identity?: boolean } = {}, ): Record { const h: Record = {} if (incoming.accept) h.accept = String(incoming.accept) if (incoming['accept-language']) h['accept-language'] = String(incoming['accept-language']) if (opts.identity) h['accept-encoding'] = 'identity' const cookie = [incoming.cookie, auth.cookie].filter(Boolean).join('; ') if (cookie) h.cookie = cookie // The edge routes on the cookie OR this header; send both so a proxy hop can't lose it. if (hasPreviewCookie(cookie)) h['x-cms-preview'] = '1' if (auth.token) h.authorization = `Bearer ${auth.token}` else if (incoming.authorization) h.authorization = String(incoming.authorization) if (auth.apiKey) h['x-api-key'] = auth.apiKey return h } /** Put the dev entry in front of (or at the end). */ export function injectDevEntry(html: string): string { const tag = '' return /<\/body>/i.test(html) ? html.replace(/<\/body>/i, `${tag}`) : html + tag }