import type { Context } from '@netlify/edge-functions' import { addBasePath, addTrailingSlash, normalizeDataUrl, normalizeLocalePath, removeBasePath, } from './util.ts' interface I18NConfig { defaultLocale: string localeDetection?: false locales: string[] } export interface RequestData { geo?: { city?: string country?: string region?: string latitude?: string longitude?: string timezone?: string } headers: Record<string, string> ip?: string method: string nextConfig?: { basePath?: string i18n?: I18NConfig | null trailingSlash?: boolean skipMiddlewareUrlNormalize?: boolean } page?: { name?: string params?: { [key: string]: string } } url: string body?: ReadableStream<Uint8Array> detectedLocale?: string } const normalizeRequestURL = ( originalURL: string, nextConfig?: RequestData['nextConfig'], ): { url: string; detectedLocale?: string } => { const url = new URL(originalURL) let pathname = removeBasePath(url.pathname, nextConfig?.basePath) // If it exists, remove the locale from the URL and store it const { detectedLocale } = normalizeLocalePath(pathname, nextConfig?.i18n?.locales) if (!nextConfig?.skipMiddlewareUrlNormalize) { // We want to run middleware for data requests and expose the URL of the // corresponding pages, so we have to normalize the URLs before running // the handler. pathname = normalizeDataUrl(pathname) // Normalizing the trailing slash based on the `trailingSlash` configuration // property from the Next.js config. if (nextConfig?.trailingSlash) { pathname = addTrailingSlash(pathname) } } url.pathname = addBasePath(pathname, nextConfig?.basePath) return { url: url.toString(), detectedLocale, } } export const buildNextRequest = ( request: Request, context: Context, nextConfig?: RequestData['nextConfig'], ): RequestData => { const { url, method, body, headers } = request const { country, subdivision, city, latitude, longitude, timezone } = context.geo const geo: RequestData['geo'] = { city, country: country?.code, region: subdivision?.code, latitude: latitude?.toString(), longitude: longitude?.toString(), timezone, } const { detectedLocale, url: normalizedUrl } = normalizeRequestURL(url, nextConfig) return { headers: Object.fromEntries(headers.entries()), geo, url: normalizedUrl, method, ip: context.ip, body: body ?? undefined, nextConfig, detectedLocale, } }