nuxt
Version:
42 lines (41 loc) • 1.76 kB
JavaScript
import { NUXT_PAGE_MATCHER } from "nuxt/internal/renderer-config";
//#region src/runtime/server/renderer/early-404.ts
const TRAILING_SLASHES_RE = /\/+$/;
const PAYLOAD_SUFFIX = "/_payload.json";
/**
* Whether a request path could match a page route, using the matcher compiled
* at build time. The lookup is deliberately looser than vue-router matching
* (decoded, case-folded, trailing slashes ignored, payload URLs matched
* against the route they belong to) so that a miss is proof no page can
* render, while a hit merely lets the request through to the app.
*/
function matchesPageRoute(pathname) {
let path = pathname;
if (path.endsWith(PAYLOAD_SUFFIX)) path = path.slice(0, -14) || "/";
if (path.length > 1) path = path.replace(TRAILING_SLASHES_RE, "") || "/";
if (path.includes("%")) try {
path = decodeURI(path);
} catch {}
return !!NUXT_PAGE_MATCHER?.("", path.toLowerCase());
}
/**
* Throw a 404 error for paths that cannot match any page route, so the app
* (and its plugins and middleware) is never loaded for them.
*
* When a `cache` route rule covers the path, its `maxAge` is advertised on
* GET/HEAD misses too, so CDNs can absorb repeat probes for unknown paths.
*/
function throwIfUnmatchedPagePath(options, event, routeOptions) {
const url = event.url;
if (matchesPageRoute(url.pathname)) return;
const path = url.pathname + url.search;
const maxAge = routeOptions.cache ? routeOptions.cache.maxAge : void 0;
if (!!maxAge && maxAge > 0 && (event.req.method === "GET" || event.req.method === "HEAD")) event.res.headers.set("cache-control", `public, max-age=${maxAge}`);
throw options.createError({
status: 404,
statusText: `Page not found: ${path}`,
data: { path }
});
}
//#endregion
export { throwIfUnmatchedPagePath };