123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287 |
- "use strict";
- Object.defineProperty(exports, "__esModule", {
- value: true
- });
- exports.default = void 0;
- var _requestMeta = require("./request-meta");
- var _pathMatch = require("../shared/lib/router/utils/path-match");
- var _removeTrailingSlash = require("../shared/lib/router/utils/remove-trailing-slash");
- var _normalizeLocalePath = require("../shared/lib/i18n/normalize-locale-path");
- var _prepareDestination = require("../shared/lib/router/utils/prepare-destination");
- var _removePathPrefix = require("../shared/lib/router/utils/remove-path-prefix");
- var _formatNextPathnameInfo = require("../shared/lib/router/utils/format-next-pathname-info");
- var _getNextPathnameInfo = require("../shared/lib/router/utils/get-next-pathname-info");
- class Router {
- /**
- * context stores information used by the router.
- */ context = new WeakMap();
- constructor({ headers =[] , fsRoutes =[] , rewrites ={
- beforeFiles: [],
- afterFiles: [],
- fallback: []
- } , redirects =[] , catchAllRoute , catchAllMiddleware =[] , dynamicRoutes =[] , pageChecker , useFileSystemPublicRoutes , nextConfig }){
- this.nextConfig = nextConfig;
- this.headers = headers;
- this.fsRoutes = [
- ...fsRoutes
- ];
- this.rewrites = rewrites;
- this.redirects = redirects;
- this.pageChecker = pageChecker;
- this.catchAllRoute = catchAllRoute;
- this.catchAllMiddleware = catchAllMiddleware;
- this.dynamicRoutes = dynamicRoutes;
- this.useFileSystemPublicRoutes = useFileSystemPublicRoutes;
- // Perform the initial route compilation.
- this.compiledRoutes = this.compileRoutes();
- this.needsRecompilation = false;
- }
- async checkPage(req, pathname) {
- pathname = (0, _normalizeLocalePath).normalizeLocalePath(pathname, this.locales).pathname;
- const context = this.context.get(req);
- if (!context) {
- throw new Error("Invariant: request is not available inside the context, this is an internal error please open an issue.");
- }
- if (context.pageChecks[pathname] !== undefined) {
- return context.pageChecks[pathname];
- }
- const result = await this.pageChecker(pathname);
- context.pageChecks[pathname] = result;
- return result;
- }
- get locales() {
- var ref;
- return ((ref = this.nextConfig.i18n) == null ? void 0 : ref.locales) || [];
- }
- get basePath() {
- return this.nextConfig.basePath || "";
- }
- setDynamicRoutes(dynamicRoutes) {
- this.dynamicRoutes = dynamicRoutes;
- this.needsRecompilation = true;
- }
- setCatchallMiddleware(catchAllMiddleware) {
- this.catchAllMiddleware = catchAllMiddleware;
- this.needsRecompilation = true;
- }
- addFsRoute(fsRoute) {
- // We use unshift so that we're sure the routes is defined before Next's
- // default routes.
- this.fsRoutes.unshift(fsRoute);
- this.needsRecompilation = true;
- }
- compileRoutes() {
- /*
- Desired routes order
- - headers
- - redirects
- - Check filesystem (including pages), if nothing found continue
- - User rewrites (checking filesystem and pages each match)
- */ const [middlewareCatchAllRoute] = this.catchAllMiddleware;
- return [
- ...middlewareCatchAllRoute ? this.fsRoutes.filter((route)=>route.name === "_next/data catchall").map((route)=>({
- ...route,
- name: "_next/data normalizing",
- check: false
- })) : [],
- ...this.headers,
- ...this.redirects,
- ...this.useFileSystemPublicRoutes && middlewareCatchAllRoute ? [
- middlewareCatchAllRoute
- ] : [],
- ...this.rewrites.beforeFiles,
- ...this.fsRoutes,
- // We only check the catch-all route if public page routes hasn't been
- // disabled
- ...this.useFileSystemPublicRoutes ? [
- {
- type: "route",
- name: "page checker",
- match: (0, _pathMatch).getPathMatch("/:path*"),
- fn: async (req, res, params, parsedUrl, upgradeHead)=>{
- const pathname = (0, _removeTrailingSlash).removeTrailingSlash(parsedUrl.pathname || "/");
- if (!pathname) {
- return {
- finished: false
- };
- }
- if (await this.checkPage(req, pathname)) {
- return this.catchAllRoute.fn(req, res, params, parsedUrl, upgradeHead);
- }
- return {
- finished: false
- };
- }
- },
- ] : [],
- ...this.rewrites.afterFiles,
- ...this.rewrites.fallback.length ? [
- {
- type: "route",
- name: "dynamic route/page check",
- match: (0, _pathMatch).getPathMatch("/:path*"),
- fn: async (req, res, _params, parsedCheckerUrl, upgradeHead)=>{
- return {
- finished: await this.checkFsRoutes(req, res, parsedCheckerUrl, upgradeHead)
- };
- }
- },
- ...this.rewrites.fallback,
- ] : [],
- // We only check the catch-all route if public page routes hasn't been
- // disabled
- ...this.useFileSystemPublicRoutes ? [
- this.catchAllRoute
- ] : [],
- ];
- }
- async checkFsRoutes(req, res, parsedUrl, upgradeHead) {
- const originalFsPathname = parsedUrl.pathname;
- const fsPathname = (0, _removePathPrefix).removePathPrefix(originalFsPathname, this.basePath);
- for (const route of this.fsRoutes){
- const params = route.match(fsPathname);
- if (params) {
- parsedUrl.pathname = fsPathname;
- const { finished } = await route.fn(req, res, params, parsedUrl);
- if (finished) {
- return true;
- }
- parsedUrl.pathname = originalFsPathname;
- }
- }
- let matchedPage = await this.checkPage(req, fsPathname);
- // If we didn't match a page check dynamic routes
- if (!matchedPage) {
- const normalizedFsPathname = (0, _normalizeLocalePath).normalizeLocalePath(fsPathname, this.locales).pathname;
- for (const dynamicRoute of this.dynamicRoutes){
- if (dynamicRoute.match(normalizedFsPathname)) {
- matchedPage = true;
- }
- }
- }
- // Matched a page or dynamic route so render it using catchAllRoute
- if (matchedPage) {
- const params = this.catchAllRoute.match(parsedUrl.pathname);
- if (!params) {
- throw new Error(`Invariant: could not match params, this is an internal error please open an issue.`);
- }
- parsedUrl.pathname = fsPathname;
- parsedUrl.query._nextBubbleNoFallback = "1";
- const { finished } = await this.catchAllRoute.fn(req, res, params, parsedUrl, upgradeHead);
- return finished;
- }
- return false;
- }
- async execute(req, res, parsedUrl, upgradeHead) {
- // Only recompile if the routes need to be recompiled, this should only
- // happen in development.
- if (this.needsRecompilation) {
- this.compiledRoutes = this.compileRoutes();
- this.needsRecompilation = false;
- }
- if (this.context.has(req)) {
- throw new Error(`Invariant: request has already been processed: ${req.url}, this is an internal error please open an issue.`);
- }
- this.context.set(req, {
- pageChecks: {}
- });
- try {
- // Create a deep copy of the parsed URL.
- const parsedUrlUpdated = {
- ...parsedUrl,
- query: {
- ...parsedUrl.query
- }
- };
- for (const route of this.compiledRoutes){
- var ref;
- // only process rewrites for upgrade request
- if (upgradeHead && route.type !== "rewrite") {
- continue;
- }
- const originalPathname = parsedUrlUpdated.pathname;
- const pathnameInfo = (0, _getNextPathnameInfo).getNextPathnameInfo(originalPathname, {
- nextConfig: this.nextConfig,
- parseData: false
- });
- if (pathnameInfo.locale && !route.matchesLocaleAPIRoutes && pathnameInfo.pathname.match(/^\/api(?:\/|$)/)) {
- continue;
- }
- if ((0, _requestMeta).getRequestMeta(req, "_nextHadBasePath")) {
- pathnameInfo.basePath = this.basePath;
- }
- const basePath = pathnameInfo.basePath;
- if (!route.matchesBasePath) {
- pathnameInfo.basePath = "";
- }
- if (route.matchesLocale && parsedUrlUpdated.query.__nextLocale && !pathnameInfo.locale) {
- pathnameInfo.locale = parsedUrlUpdated.query.__nextLocale;
- }
- if (!route.matchesLocale && pathnameInfo.locale === ((ref = this.nextConfig.i18n) == null ? void 0 : ref.defaultLocale) && pathnameInfo.locale) {
- pathnameInfo.locale = undefined;
- }
- if (route.matchesTrailingSlash && (0, _requestMeta).getRequestMeta(req, "__nextHadTrailingSlash")) {
- pathnameInfo.trailingSlash = true;
- }
- const matchPathname = (0, _formatNextPathnameInfo).formatNextPathnameInfo({
- ignorePrefix: true,
- ...pathnameInfo
- });
- let params = route.match(matchPathname);
- if ((route.has || route.missing) && params) {
- const hasParams = (0, _prepareDestination).matchHas(req, parsedUrlUpdated.query, route.has, route.missing);
- if (hasParams) {
- Object.assign(params, hasParams);
- } else {
- params = false;
- }
- }
- /**
- * If it is a matcher that doesn't match the basePath (like the public
- * directory) but Next.js is configured to use a basePath that was
- * never there, we consider this an invalid match and keep routing.
- */ if (params && this.basePath && !route.matchesBasePath && !(0, _requestMeta).getRequestMeta(req, "_nextDidRewrite") && !basePath) {
- continue;
- }
- if (params) {
- const isNextDataNormalizing = route.name === "_next/data normalizing";
- if (isNextDataNormalizing) {
- (0, _requestMeta).addRequestMeta(req, "_nextDataNormalizing", true);
- }
- parsedUrlUpdated.pathname = matchPathname;
- const result = await route.fn(req, res, params, parsedUrlUpdated, upgradeHead);
- if (isNextDataNormalizing) {
- (0, _requestMeta).addRequestMeta(req, "_nextDataNormalizing", false);
- }
- if (result.finished) {
- return true;
- }
- if (result.pathname) {
- parsedUrlUpdated.pathname = result.pathname;
- } else {
- // since the fs route didn't finish routing we need to re-add the
- // basePath to continue checking with the basePath present
- parsedUrlUpdated.pathname = originalPathname;
- }
- if (result.query) {
- parsedUrlUpdated.query = {
- ...(0, _requestMeta).getNextInternalQuery(parsedUrlUpdated.query),
- ...result.query
- };
- }
- // check filesystem
- if (route.check && await this.checkFsRoutes(req, res, parsedUrlUpdated)) {
- return true;
- }
- }
- }
- // All routes were tested, none were found.
- return false;
- } finally{
- this.context.delete(req);
- }
- }
- }
- exports.default = Router;
- //# sourceMappingURL=router.js.map
|