123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359 |
- "use strict";
- Object.defineProperty(exports, "__esModule", {
- value: true
- });
- exports.interpolateDynamicPath = interpolateDynamicPath;
- exports.getUtils = getUtils;
- exports.vercelHeader = void 0;
- var _url = require("url");
- var _querystring = require("querystring");
- var _normalizeLocalePath = require("../../../../shared/lib/i18n/normalize-locale-path");
- var _pathMatch = require("../../../../shared/lib/router/utils/path-match");
- var _routeRegex = require("../../../../shared/lib/router/utils/route-regex");
- var _routeMatcher = require("../../../../shared/lib/router/utils/route-matcher");
- var _prepareDestination = require("../../../../shared/lib/router/utils/prepare-destination");
- var _acceptHeader = require("../../../../server/accept-header");
- var _detectLocaleCookie = require("../../../../shared/lib/i18n/detect-locale-cookie");
- var _detectDomainLocale = require("../../../../shared/lib/i18n/detect-domain-locale");
- var _denormalizePagePath = require("../../../../shared/lib/page-path/denormalize-page-path");
- var _cookie = _interopRequireDefault(require("next/dist/compiled/cookie"));
- var _constants = require("../../../../shared/lib/constants");
- var _requestMeta = require("../../../../server/request-meta");
- var _removeTrailingSlash = require("../../../../shared/lib/router/utils/remove-trailing-slash");
- function _interopRequireDefault(obj) {
- return obj && obj.__esModule ? obj : {
- default: obj
- };
- }
- const vercelHeader = "x-vercel-id";
- exports.vercelHeader = vercelHeader;
- function interpolateDynamicPath(pathname, params, defaultRouteRegex) {
- if (!defaultRouteRegex) return pathname;
- for (const param of Object.keys(defaultRouteRegex.groups)){
- const { optional , repeat } = defaultRouteRegex.groups[param];
- let builtParam = `[${repeat ? "..." : ""}${param}]`;
- if (optional) {
- builtParam = `[${builtParam}]`;
- }
- const paramIdx = pathname.indexOf(builtParam);
- if (paramIdx > -1) {
- let paramValue;
- if (Array.isArray(params[param])) {
- paramValue = params[param].map((v)=>v && encodeURIComponent(v)).join("/");
- } else {
- paramValue = params[param] && encodeURIComponent(params[param]);
- }
- pathname = pathname.slice(0, paramIdx) + (paramValue || "") + pathname.slice(paramIdx + builtParam.length);
- }
- }
- return pathname;
- }
- function getUtils({ page , i18n , basePath , rewrites , pageIsDynamic , trailingSlash }) {
- let defaultRouteRegex;
- let dynamicRouteMatcher;
- let defaultRouteMatches;
- if (pageIsDynamic) {
- defaultRouteRegex = (0, _routeRegex).getNamedRouteRegex(page);
- dynamicRouteMatcher = (0, _routeMatcher).getRouteMatcher(defaultRouteRegex);
- defaultRouteMatches = dynamicRouteMatcher(page);
- }
- function handleRewrites(req, parsedUrl) {
- const rewriteParams = {};
- let fsPathname = parsedUrl.pathname;
- const matchesPage = ()=>{
- const fsPathnameNoSlash = (0, _removeTrailingSlash).removeTrailingSlash(fsPathname || "");
- return fsPathnameNoSlash === (0, _removeTrailingSlash).removeTrailingSlash(page) || (dynamicRouteMatcher == null ? void 0 : dynamicRouteMatcher(fsPathnameNoSlash));
- };
- const checkRewrite = (rewrite)=>{
- const matcher = (0, _pathMatch).getPathMatch(rewrite.source + (trailingSlash ? "(/)?" : ""), {
- removeUnnamedParams: true,
- strict: true
- });
- let params = matcher(parsedUrl.pathname);
- if ((rewrite.has || rewrite.missing) && params) {
- const hasParams = (0, _prepareDestination).matchHas(req, parsedUrl.query, rewrite.has, rewrite.missing);
- if (hasParams) {
- Object.assign(params, hasParams);
- } else {
- params = false;
- }
- }
- if (params) {
- const { parsedDestination , destQuery } = (0, _prepareDestination).prepareDestination({
- appendParamsToQuery: true,
- destination: rewrite.destination,
- params: params,
- query: parsedUrl.query
- });
- // if the rewrite destination is external break rewrite chain
- if (parsedDestination.protocol) {
- return true;
- }
- Object.assign(rewriteParams, destQuery, params);
- Object.assign(parsedUrl.query, parsedDestination.query);
- delete parsedDestination.query;
- Object.assign(parsedUrl, parsedDestination);
- fsPathname = parsedUrl.pathname;
- if (basePath) {
- fsPathname = fsPathname.replace(new RegExp(`^${basePath}`), "") || "/";
- }
- if (i18n) {
- const destLocalePathResult = (0, _normalizeLocalePath).normalizeLocalePath(fsPathname, i18n.locales);
- fsPathname = destLocalePathResult.pathname;
- parsedUrl.query.nextInternalLocale = destLocalePathResult.detectedLocale || params.nextInternalLocale;
- }
- if (fsPathname === page) {
- return true;
- }
- if (pageIsDynamic && dynamicRouteMatcher) {
- const dynamicParams = dynamicRouteMatcher(fsPathname);
- if (dynamicParams) {
- parsedUrl.query = {
- ...parsedUrl.query,
- ...dynamicParams
- };
- return true;
- }
- }
- }
- return false;
- };
- for (const rewrite1 of rewrites.beforeFiles || []){
- checkRewrite(rewrite1);
- }
- if (fsPathname !== page) {
- let finished = false;
- for (const rewrite of rewrites.afterFiles || []){
- finished = checkRewrite(rewrite);
- if (finished) break;
- }
- if (!finished && !matchesPage()) {
- for (const rewrite of rewrites.fallback || []){
- finished = checkRewrite(rewrite);
- if (finished) break;
- }
- }
- }
- return rewriteParams;
- }
- function handleBasePath(req, parsedUrl) {
- // always strip the basePath if configured since it is required
- req.url = req.url.replace(new RegExp(`^${basePath}`), "") || "/";
- parsedUrl.pathname = parsedUrl.pathname.replace(new RegExp(`^${basePath}`), "") || "/";
- }
- function getParamsFromRouteMatches(req, renderOpts, detectedLocale) {
- return (0, _routeMatcher).getRouteMatcher(function() {
- const { groups , routeKeys } = defaultRouteRegex;
- return {
- re: {
- // Simulate a RegExp match from the \`req.url\` input
- exec: (str)=>{
- const obj = (0, _querystring).parse(str);
- const matchesHasLocale = i18n && detectedLocale && obj["1"] === detectedLocale;
- // favor named matches if available
- const routeKeyNames = Object.keys(routeKeys || {});
- const filterLocaleItem = (val)=>{
- if (i18n) {
- // locale items can be included in route-matches
- // for fallback SSG pages so ensure they are
- // filtered
- const isCatchAll = Array.isArray(val);
- const _val = isCatchAll ? val[0] : val;
- if (typeof _val === "string" && i18n.locales.some((item)=>{
- if (item.toLowerCase() === _val.toLowerCase()) {
- detectedLocale = item;
- renderOpts.locale = detectedLocale;
- return true;
- }
- return false;
- })) {
- // remove the locale item from the match
- if (isCatchAll) {
- val.splice(0, 1);
- }
- // the value is only a locale item and
- // shouldn't be added
- return isCatchAll ? val.length === 0 : true;
- }
- }
- return false;
- };
- if (routeKeyNames.every((name)=>obj[name])) {
- return routeKeyNames.reduce((prev, keyName)=>{
- const paramName = routeKeys == null ? void 0 : routeKeys[keyName];
- if (paramName && !filterLocaleItem(obj[keyName])) {
- prev[groups[paramName].pos] = obj[keyName];
- }
- return prev;
- }, {});
- }
- return Object.keys(obj).reduce((prev, key)=>{
- if (!filterLocaleItem(obj[key])) {
- let normalizedKey = key;
- if (matchesHasLocale) {
- normalizedKey = parseInt(key, 10) - 1 + "";
- }
- return Object.assign(prev, {
- [normalizedKey]: obj[key]
- });
- }
- return prev;
- }, {});
- }
- },
- groups
- };
- }())(req.headers["x-now-route-matches"]);
- }
- function normalizeVercelUrl(req, trustQuery, paramKeys) {
- // make sure to normalize req.url on Vercel to strip dynamic params
- // from the query which are added during routing
- if (pageIsDynamic && trustQuery && defaultRouteRegex) {
- const _parsedUrl = (0, _url).parse(req.url, true);
- delete _parsedUrl.search;
- for (const param of paramKeys || Object.keys(defaultRouteRegex.groups)){
- delete _parsedUrl.query[param];
- }
- req.url = (0, _url).format(_parsedUrl);
- }
- }
- function normalizeDynamicRouteParams(params, ignoreOptional) {
- let hasValidParams = true;
- if (!defaultRouteRegex) return {
- params,
- hasValidParams: false
- };
- params = Object.keys(defaultRouteRegex.groups).reduce((prev, key)=>{
- let value = params[key];
- // if the value matches the default value we can't rely
- // on the parsed params, this is used to signal if we need
- // to parse x-now-route-matches or not
- const defaultValue = defaultRouteMatches[key];
- const isOptional = defaultRouteRegex.groups[key].optional;
- const isDefaultValue = Array.isArray(defaultValue) ? defaultValue.some((defaultVal)=>{
- return Array.isArray(value) ? value.some((val)=>val.includes(defaultVal)) : value == null ? void 0 : value.includes(defaultVal);
- }) : value == null ? void 0 : value.includes(defaultValue);
- if (isDefaultValue || typeof value === "undefined" && !(isOptional && ignoreOptional)) {
- hasValidParams = false;
- }
- // non-provided optional values should be undefined so normalize
- // them to undefined
- if (isOptional && (!value || Array.isArray(value) && value.length === 1 && // fallback optional catch-all SSG pages have
- // [[...paramName]] for the root path on Vercel
- (value[0] === "index" || value[0] === `[[...${key}]]`))) {
- value = undefined;
- delete params[key];
- }
- // query values from the proxy aren't already split into arrays
- // so make sure to normalize catch-all values
- if (value && typeof value === "string" && defaultRouteRegex.groups[key].repeat) {
- value = value.split("/");
- }
- if (value) {
- prev[key] = value;
- }
- return prev;
- }, {});
- return {
- params,
- hasValidParams
- };
- }
- function handleLocale(req, res, parsedUrl, routeNoAssetPath, shouldNotRedirect) {
- if (!i18n) return;
- const pathname = parsedUrl.pathname || "/";
- let defaultLocale = i18n.defaultLocale;
- let detectedLocale = (0, _detectLocaleCookie).detectLocaleCookie(req, i18n.locales);
- let acceptPreferredLocale;
- try {
- acceptPreferredLocale = i18n.localeDetection !== false ? (0, _acceptHeader).acceptLanguage(req.headers["accept-language"], i18n.locales) : detectedLocale;
- } catch (_) {
- acceptPreferredLocale = detectedLocale;
- }
- const { host } = req.headers || {};
- // remove port from host and remove port if present
- const hostname = host && host.split(":")[0].toLowerCase();
- const detectedDomain = (0, _detectDomainLocale).detectDomainLocale(i18n.domains, hostname);
- if (detectedDomain) {
- defaultLocale = detectedDomain.defaultLocale;
- detectedLocale = defaultLocale;
- (0, _requestMeta).addRequestMeta(req, "__nextIsLocaleDomain", true);
- }
- // if not domain specific locale use accept-language preferred
- detectedLocale = detectedLocale || acceptPreferredLocale;
- let localeDomainRedirect;
- const localePathResult = (0, _normalizeLocalePath).normalizeLocalePath(pathname, i18n.locales);
- routeNoAssetPath = (0, _normalizeLocalePath).normalizeLocalePath(routeNoAssetPath, i18n.locales).pathname;
- if (localePathResult.detectedLocale) {
- detectedLocale = localePathResult.detectedLocale;
- req.url = (0, _url).format({
- ...parsedUrl,
- pathname: localePathResult.pathname
- });
- (0, _requestMeta).addRequestMeta(req, "__nextStrippedLocale", true);
- parsedUrl.pathname = localePathResult.pathname;
- }
- // If a detected locale is a domain specific locale and we aren't already
- // on that domain and path prefix redirect to it to prevent duplicate
- // content from multiple domains
- if (detectedDomain) {
- const localeToCheck = localePathResult.detectedLocale ? detectedLocale : acceptPreferredLocale;
- const matchedDomain = (0, _detectDomainLocale).detectDomainLocale(i18n.domains, undefined, localeToCheck);
- if (matchedDomain && matchedDomain.domain !== detectedDomain.domain) {
- localeDomainRedirect = `http${matchedDomain.http ? "" : "s"}://${matchedDomain.domain}/${localeToCheck === matchedDomain.defaultLocale ? "" : localeToCheck}`;
- }
- }
- const denormalizedPagePath = (0, _denormalizePagePath).denormalizePagePath(pathname);
- const detectedDefaultLocale = !detectedLocale || detectedLocale.toLowerCase() === defaultLocale.toLowerCase();
- const shouldStripDefaultLocale = false;
- // detectedDefaultLocale &&
- // denormalizedPagePath.toLowerCase() === \`/\${i18n.defaultLocale.toLowerCase()}\`
- const shouldAddLocalePrefix = !detectedDefaultLocale && denormalizedPagePath === "/";
- detectedLocale = detectedLocale || i18n.defaultLocale;
- if (!shouldNotRedirect && !req.headers[vercelHeader] && i18n.localeDetection !== false && (localeDomainRedirect || shouldAddLocalePrefix || shouldStripDefaultLocale)) {
- // set the NEXT_LOCALE cookie when a user visits the default locale
- // with the locale prefix so that they aren't redirected back to
- // their accept-language preferred locale
- if (shouldStripDefaultLocale && acceptPreferredLocale !== defaultLocale) {
- const previous = res.getHeader("set-cookie");
- res.setHeader("set-cookie", [
- ...typeof previous === "string" ? [
- previous
- ] : Array.isArray(previous) ? previous : [],
- _cookie.default.serialize("NEXT_LOCALE", defaultLocale, {
- httpOnly: true,
- path: "/"
- }),
- ]);
- }
- res.setHeader("Location", (0, _url).format({
- // make sure to include any query values when redirecting
- ...parsedUrl,
- pathname: localeDomainRedirect ? localeDomainRedirect : shouldStripDefaultLocale ? basePath || "/" : `${basePath}/${detectedLocale}`
- }));
- res.statusCode = _constants.TEMPORARY_REDIRECT_STATUS;
- res.end();
- return;
- }
- detectedLocale = localePathResult.detectedLocale || detectedDomain && detectedDomain.defaultLocale || defaultLocale;
- return {
- defaultLocale,
- detectedLocale,
- routeNoAssetPath
- };
- }
- return {
- handleLocale,
- handleRewrites,
- handleBasePath,
- defaultRouteRegex,
- normalizeVercelUrl,
- dynamicRouteMatcher,
- defaultRouteMatches,
- getParamsFromRouteMatches,
- normalizeDynamicRouteParams,
- interpolateDynamicPath: (pathname, params)=>interpolateDynamicPath(pathname, params, defaultRouteRegex)
- };
- }
- //# sourceMappingURL=utils.js.map
|