UNPKG

astro

Version:

Astro is a modern site builder with web best practices, performance, and DX front-of-mind.

117 lines (116 loc) 3.68 kB
import { shouldAppendForwardSlash } from "../build/util.js"; import { originPathnameSymbol } from "../constants.js"; import { AstroError, AstroErrorData } from "../errors/index.js"; import { appendForwardSlash, joinPaths, prependForwardSlash, removeTrailingForwardSlash } from "../path.js"; import { createRequest } from "../request.js"; import { DEFAULT_404_ROUTE } from "./astro-designed-error-pages.js"; function findRouteToRewrite({ payload, routes, request, trailingSlash, buildFormat, base }) { let newUrl = void 0; if (payload instanceof URL) { newUrl = payload; } else if (payload instanceof Request) { newUrl = new URL(payload.url); } else { newUrl = new URL(payload, new URL(request.url).origin); } let pathname = newUrl.pathname; const shouldAppendSlash = shouldAppendForwardSlash(trailingSlash, buildFormat); if (base !== "/") { const isBasePathRequest = newUrl.pathname === base || newUrl.pathname === removeTrailingForwardSlash(base); if (isBasePathRequest) { pathname = shouldAppendSlash ? "/" : ""; } else if (newUrl.pathname.startsWith(base)) { pathname = shouldAppendSlash ? appendForwardSlash(newUrl.pathname) : removeTrailingForwardSlash(newUrl.pathname); pathname = pathname.slice(base.length); } } if (!pathname.startsWith("/") && shouldAppendSlash && newUrl.pathname.endsWith("/")) { pathname = prependForwardSlash(pathname); } if (pathname === "/" && base !== "/" && !shouldAppendSlash) { pathname = ""; } if (base !== "/" && (pathname === "" || pathname === "/") && !shouldAppendSlash) { newUrl.pathname = removeTrailingForwardSlash(base); } else { newUrl.pathname = joinPaths(...[base, pathname].filter(Boolean)); } const decodedPathname = decodeURI(pathname); let foundRoute; for (const route of routes) { if (route.pattern.test(decodedPathname)) { foundRoute = route; break; } } if (foundRoute) { return { routeData: foundRoute, newUrl, pathname: decodedPathname }; } else { const custom404 = routes.find((route) => route.route === "/404"); if (custom404) { return { routeData: custom404, newUrl, pathname }; } else { return { routeData: DEFAULT_404_ROUTE, newUrl, pathname }; } } } function copyRequest(newUrl, oldRequest, isPrerendered, logger, routePattern) { if (oldRequest.bodyUsed) { throw new AstroError(AstroErrorData.RewriteWithBodyUsed); } return createRequest({ url: newUrl, method: oldRequest.method, body: oldRequest.body, isPrerendered, logger, headers: isPrerendered ? {} : oldRequest.headers, routePattern, init: { referrer: oldRequest.referrer, referrerPolicy: oldRequest.referrerPolicy, mode: oldRequest.mode, credentials: oldRequest.credentials, cache: oldRequest.cache, redirect: oldRequest.redirect, integrity: oldRequest.integrity, signal: oldRequest.signal, keepalive: oldRequest.keepalive, // https://fetch.spec.whatwg.org/#dom-request-duplex // @ts-expect-error It isn't part of the types, but undici accepts it and it allows to carry over the body to a new request duplex: "half" } }); } function setOriginPathname(request, pathname) { Reflect.set(request, originPathnameSymbol, encodeURIComponent(pathname)); } function getOriginPathname(request) { const origin = Reflect.get(request, originPathnameSymbol); if (origin) { return decodeURIComponent(origin); } return new URL(request.url).pathname; } export { copyRequest, findRouteToRewrite, getOriginPathname, setOriginPathname };