UNPKG

astro

Version:

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

73 lines (72 loc) • 3.34 kB
import { AstroCookies } from "../cookies/index.js"; import { getEnvironment } from "../environment/index.js"; import { ForbiddenRewrite } from "../errors/errors-data.js"; import { AstroError } from "../errors/errors.js"; import { handleMiddleware } from "../middleware/astro-middleware.js"; import { handlePages } from "../pages/handler.js"; import { getParams } from "../render/params-and-props.js"; import { copyRequest, setOriginPathname } from "../routing/rewrite.js"; import { createNormalizedUrl } from "../util/normalized-url.js"; /** * Validates and applies a rewrite target to the given `FetchState`. * * - Validates that SSR→prerender rewrites are not attempted (except * for i18n fallback routes). * - Mutates `state` to reflect the new route: request, URL, cookies, * params, pathname, component instance, etc. * - Invalidates cached API contexts so they're re-derived from the * new route. * * Called by both `executeRewrite()` (user-triggered `Astro.rewrite`) * and `handleMiddleware` (middleware `next(payload)`). */ export function applyRewriteToState(state, payload, { routeData, componentInstance, newUrl, pathname }, { mergeCookies = false } = {}) { const oldPathname = state.pathname; // Disallow SSR→prerender rewrites: the prerendered route becomes a // static HTML file during build and isn't available in the server // manifest. Allow i18n fallback routes as an exception. const isI18nFallback = routeData.fallbackRoutes && routeData.fallbackRoutes.length > 0; if (state.manifest.serverLike && !state.routeData.prerender && routeData.prerender && !isI18nFallback) { throw new AstroError({ ...ForbiddenRewrite, message: ForbiddenRewrite.message(state.pathname, pathname, routeData.component), hint: ForbiddenRewrite.hint(routeData.component) }); } state.routeData = routeData; state.componentInstance = componentInstance; if (payload instanceof Request) { state.request = payload; } else { state.request = copyRequest(newUrl, state.request, routeData.prerender, state.logger, state.routeData.route); } state.url = createNormalizedUrl(state.request.url); if (mergeCookies) { const newCookies = new AstroCookies(state.request, state.logger); if (state.cookies) { newCookies.merge(state.cookies); } state.cookies = newCookies; } state.params = getParams(routeData, pathname); state.pathname = pathname; state.isRewriting = true; state.status = 200; setOriginPathname(state.request, oldPathname, state.manifest.trailingSlash, state.manifest.buildFormat); // Props / API contexts are derived from the (now-changed) route; // drop the cached ones so they're re-built. state.invalidateContexts(); } /** * Executes a user-triggered rewrite (`Astro.rewrite(...)` / * `ctx.rewrite(...)`) against a `FetchState`. Resolves the rewrite * target via the environment's `tryRewrite`, validates it, mutates the * `FetchState` to reflect the new route, and re-runs the middleware * and page dispatch to produce the new response. */ export async function executeRewrite(state, payload) { state.logger.debug("router", "Calling rewrite: ", payload); const result = await getEnvironment(state.manifest).tryRewrite(state.manifest, payload, state.request); applyRewriteToState(state, payload, result, { mergeCookies: true }); return handleMiddleware(state, handlePages); }