171 lines
9.3 KiB
JavaScript
171 lines
9.3 KiB
JavaScript
'use strict';
|
|
|
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
|
var server = require('next/server');
|
|
var config = require('../routing/config.js');
|
|
var constants = require('../shared/constants.js');
|
|
var utils$1 = require('../shared/utils.js');
|
|
var getAlternateLinksHeaderValue = require('./getAlternateLinksHeaderValue.js');
|
|
var resolveLocale = require('./resolveLocale.js');
|
|
var syncCookie = require('./syncCookie.js');
|
|
var utils = require('./utils.js');
|
|
|
|
function createMiddleware(routing, /** @deprecated Should be passed via the first parameter `routing` instead (ideally defined with `defineRouting`) */
|
|
options) {
|
|
var _options$alternateLin, _options$localeDetect, _options$localeCookie;
|
|
const resolvedRouting = config.receiveRoutingConfig({
|
|
...routing,
|
|
alternateLinks: (_options$alternateLin = options === null || options === void 0 ? void 0 : options.alternateLinks) !== null && _options$alternateLin !== void 0 ? _options$alternateLin : routing.alternateLinks,
|
|
localeDetection: (_options$localeDetect = options === null || options === void 0 ? void 0 : options.localeDetection) !== null && _options$localeDetect !== void 0 ? _options$localeDetect : routing.localeDetection,
|
|
localeCookie: (_options$localeCookie = options === null || options === void 0 ? void 0 : options.localeCookie) !== null && _options$localeCookie !== void 0 ? _options$localeCookie : routing.localeCookie
|
|
});
|
|
return function middleware(request) {
|
|
var _resolvedRouting$doma;
|
|
let unsafeExternalPathname;
|
|
try {
|
|
// Resolve potential foreign symbols (e.g. /ja/%E7%B4%84 → /ja/約))
|
|
unsafeExternalPathname = decodeURI(request.nextUrl.pathname);
|
|
} catch (_unused) {
|
|
// In case an invalid pathname is encountered, forward
|
|
// it to Next.js which in turn responds with a 400
|
|
return server.NextResponse.next();
|
|
}
|
|
|
|
// Sanitize malicious URIs to prevent open redirect attacks due to
|
|
// decodeURI doesn't escape encoded backslashes ('%5C' & '%5c')
|
|
const externalPathname = utils.sanitizePathname(unsafeExternalPathname);
|
|
const {
|
|
domain,
|
|
locale
|
|
} = resolveLocale.default(resolvedRouting, request.headers, request.cookies, externalPathname);
|
|
const hasMatchedDefaultLocale = domain ? domain.defaultLocale === locale : locale === resolvedRouting.defaultLocale;
|
|
const domainsConfig = ((_resolvedRouting$doma = resolvedRouting.domains) === null || _resolvedRouting$doma === void 0 ? void 0 : _resolvedRouting$doma.filter(curDomain => utils.isLocaleSupportedOnDomain(locale, curDomain))) || [];
|
|
const hasUnknownHost = resolvedRouting.domains != null && !domain;
|
|
function rewrite(url) {
|
|
const urlObj = new URL(url, request.url);
|
|
if (request.nextUrl.basePath) {
|
|
urlObj.pathname = utils.applyBasePath(urlObj.pathname, request.nextUrl.basePath);
|
|
}
|
|
const headers = new Headers(request.headers);
|
|
headers.set(constants.HEADER_LOCALE_NAME, locale);
|
|
return server.NextResponse.rewrite(urlObj, {
|
|
request: {
|
|
headers
|
|
}
|
|
});
|
|
}
|
|
function redirect(url, redirectDomain) {
|
|
const urlObj = new URL(url, request.url);
|
|
urlObj.pathname = utils$1.normalizeTrailingSlash(urlObj.pathname);
|
|
if (domainsConfig.length > 0 && !redirectDomain && domain) {
|
|
const bestMatchingDomain = utils.getBestMatchingDomain(domain, locale, domainsConfig);
|
|
if (bestMatchingDomain) {
|
|
redirectDomain = bestMatchingDomain.domain;
|
|
if (bestMatchingDomain.defaultLocale === locale && resolvedRouting.localePrefix.mode === 'as-needed') {
|
|
urlObj.pathname = utils.getNormalizedPathname(urlObj.pathname, resolvedRouting.locales, resolvedRouting.localePrefix);
|
|
}
|
|
}
|
|
}
|
|
if (redirectDomain) {
|
|
urlObj.host = redirectDomain;
|
|
if (request.headers.get('x-forwarded-host')) {
|
|
var _request$headers$get, _request$headers$get2;
|
|
urlObj.protocol = (_request$headers$get = request.headers.get('x-forwarded-proto')) !== null && _request$headers$get !== void 0 ? _request$headers$get : request.nextUrl.protocol;
|
|
urlObj.port = (_request$headers$get2 = request.headers.get('x-forwarded-port')) !== null && _request$headers$get2 !== void 0 ? _request$headers$get2 : '';
|
|
}
|
|
}
|
|
if (request.nextUrl.basePath) {
|
|
urlObj.pathname = utils.applyBasePath(urlObj.pathname, request.nextUrl.basePath);
|
|
}
|
|
return server.NextResponse.redirect(urlObj.toString());
|
|
}
|
|
const unprefixedExternalPathname = utils.getNormalizedPathname(externalPathname, resolvedRouting.locales, resolvedRouting.localePrefix);
|
|
const pathnameMatch = utils.getPathnameMatch(externalPathname, resolvedRouting.locales, resolvedRouting.localePrefix);
|
|
const hasLocalePrefix = pathnameMatch != null;
|
|
const isUnprefixedRouting = resolvedRouting.localePrefix.mode === 'never' || hasMatchedDefaultLocale && resolvedRouting.localePrefix.mode === 'as-needed';
|
|
let response;
|
|
let internalTemplateName;
|
|
let unprefixedInternalPathname = unprefixedExternalPathname;
|
|
const pathnames = resolvedRouting.pathnames;
|
|
if (pathnames) {
|
|
let resolvedTemplateLocale;
|
|
[resolvedTemplateLocale, internalTemplateName] = utils.getInternalTemplate(pathnames, unprefixedExternalPathname, locale);
|
|
if (internalTemplateName) {
|
|
const pathnameConfig = pathnames[internalTemplateName];
|
|
const localeTemplate = typeof pathnameConfig === 'string' ? pathnameConfig : pathnameConfig[locale];
|
|
if (utils$1.matchesPathname(localeTemplate, unprefixedExternalPathname)) {
|
|
unprefixedInternalPathname = utils.formatTemplatePathname(unprefixedExternalPathname, localeTemplate, internalTemplateName);
|
|
} else {
|
|
let sourceTemplate;
|
|
if (resolvedTemplateLocale) {
|
|
// A localized pathname from another locale has matched
|
|
sourceTemplate = typeof pathnameConfig === 'string' ? pathnameConfig : pathnameConfig[resolvedTemplateLocale];
|
|
} else {
|
|
// An internal pathname has matched that
|
|
// doesn't have a localized pathname
|
|
sourceTemplate = internalTemplateName;
|
|
}
|
|
const localePrefix = isUnprefixedRouting ? undefined : utils$1.getLocalePrefix(locale, resolvedRouting.localePrefix);
|
|
const template = utils.formatTemplatePathname(unprefixedExternalPathname, sourceTemplate, localeTemplate);
|
|
response = redirect(utils.formatPathname(template, localePrefix, request.nextUrl.search));
|
|
}
|
|
}
|
|
}
|
|
if (!response) {
|
|
if (unprefixedInternalPathname === '/' && !hasLocalePrefix) {
|
|
if (isUnprefixedRouting) {
|
|
response = rewrite(utils.formatPathname(unprefixedInternalPathname, utils.getLocaleAsPrefix(locale), request.nextUrl.search));
|
|
} else {
|
|
response = redirect(utils.formatPathname(unprefixedExternalPathname, utils$1.getLocalePrefix(locale, resolvedRouting.localePrefix), request.nextUrl.search));
|
|
}
|
|
} else {
|
|
const internalHref = utils.formatPathname(unprefixedInternalPathname, utils.getLocaleAsPrefix(locale), request.nextUrl.search);
|
|
if (hasLocalePrefix) {
|
|
const externalHref = utils.formatPathname(unprefixedExternalPathname, pathnameMatch.prefix, request.nextUrl.search);
|
|
if (resolvedRouting.localePrefix.mode === 'never') {
|
|
response = redirect(utils.formatPathname(unprefixedExternalPathname, undefined, request.nextUrl.search));
|
|
} else if (pathnameMatch.exact) {
|
|
if (hasMatchedDefaultLocale && isUnprefixedRouting) {
|
|
response = redirect(utils.formatPathname(unprefixedExternalPathname, undefined, request.nextUrl.search));
|
|
} else {
|
|
if (resolvedRouting.domains) {
|
|
const pathDomain = utils.getBestMatchingDomain(domain, pathnameMatch.locale, domainsConfig);
|
|
if ((domain === null || domain === void 0 ? void 0 : domain.domain) !== (pathDomain === null || pathDomain === void 0 ? void 0 : pathDomain.domain) && !hasUnknownHost) {
|
|
response = redirect(externalHref, pathDomain === null || pathDomain === void 0 ? void 0 : pathDomain.domain);
|
|
} else {
|
|
response = rewrite(internalHref);
|
|
}
|
|
} else {
|
|
response = rewrite(internalHref);
|
|
}
|
|
}
|
|
} else {
|
|
response = redirect(externalHref);
|
|
}
|
|
} else {
|
|
if (isUnprefixedRouting) {
|
|
response = rewrite(internalHref);
|
|
} else {
|
|
response = redirect(utils.formatPathname(unprefixedExternalPathname, utils$1.getLocalePrefix(locale, resolvedRouting.localePrefix), request.nextUrl.search));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (resolvedRouting.localeDetection && resolvedRouting.localeCookie) {
|
|
syncCookie.default(request, response, locale, resolvedRouting.localeCookie);
|
|
}
|
|
if (resolvedRouting.localePrefix.mode !== 'never' && resolvedRouting.alternateLinks && resolvedRouting.locales.length > 1) {
|
|
response.headers.set('Link', getAlternateLinksHeaderValue.default({
|
|
routing: resolvedRouting,
|
|
localizedPathnames: internalTemplateName != null && pathnames ? pathnames[internalTemplateName] : undefined,
|
|
request,
|
|
resolvedLocale: locale
|
|
}));
|
|
}
|
|
return response;
|
|
};
|
|
}
|
|
|
|
exports.default = createMiddleware;
|