'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;