From 6c14a3895f06a268a8f82cf818090ce59a44ef1a Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Mon, 13 Jun 2022 15:09:59 -0500 Subject: [PATCH] Fix rewrite/dynamic interpolation E2E cases --- .../loaders/next-serverless-loader/utils.ts | 10 +++- packages/next/server/base-server.ts | 54 ++++++++++--------- test/production/required-server-files.test.ts | 17 ++++++ 3 files changed, 54 insertions(+), 27 deletions(-) diff --git a/packages/next/build/webpack/loaders/next-serverless-loader/utils.ts b/packages/next/build/webpack/loaders/next-serverless-loader/utils.ts index 2703a90e9d227..dffb65244b408 100644 --- a/packages/next/build/webpack/loaders/next-serverless-loader/utils.ts +++ b/packages/next/build/webpack/loaders/next-serverless-loader/utils.ts @@ -340,7 +340,10 @@ export function getUtils({ } } - function normalizeDynamicRouteParams(params: ParsedUrlQuery) { + function normalizeDynamicRouteParams( + params: ParsedUrlQuery, + ignoreOptional?: boolean + ) { let hasValidParams = true if (!defaultRouteRegex) return { params, hasValidParams: false } @@ -361,7 +364,10 @@ export function getUtils({ }) : value?.includes(defaultValue as string) - if (isDefaultValue || (typeof value === 'undefined' && !isOptional)) { + if ( + isDefaultValue || + (typeof value === 'undefined' && !(isOptional && ignoreOptional)) + ) { hasValidParams = false } diff --git a/packages/next/server/base-server.ts b/packages/next/server/base-server.ts index 373f7b95bfecc..309c4bdcacc17 100644 --- a/packages/next/server/base-server.ts +++ b/packages/next/server/base-server.ts @@ -517,27 +517,20 @@ export default abstract class Server { parsedUrl.query ) + // for prerendered ISR paths we attempt parsing the route + // params from the URL directly as route-matches may not + // contain the correct values due to the filesystem path + // matching before the dynamic route has been matched if ( - !isDynamicRoute(normalizedUrlPath) || - !isDynamicRoute(matchedPath) + !paramsResult.hasValidParams && + pageIsDynamic && + !isDynamicRoute(normalizedUrlPath) ) { - // we favor matching against req.url although if there's a - // rewrite and it's SSR we use the x-matched-path instead - let matcherRes = utils.dynamicRouteMatcher?.(normalizedUrlPath) + let matcherParams = utils.dynamicRouteMatcher?.(normalizedUrlPath) - if (!matcherRes) { - matcherRes = utils.dynamicRouteMatcher?.(matchedPath) - } - const parsedResult = utils.normalizeDynamicRouteParams( - matcherRes || {} - ) - - if (parsedResult.hasValidParams) { - if (paramsResult.hasValidParams) { - Object.assign(paramsResult.params, parsedResult.params) - } else { - paramsResult = parsedResult - } + if (matcherParams) { + Object.assign(paramsResult.params, matcherParams) + paramsResult.hasValidParams = true } } @@ -547,9 +540,8 @@ export default abstract class Server { if ( req.headers['x-now-route-matches'] && - (!paramsResult.hasValidParams || - (isDynamicRoute(matchedPath) && - isDynamicRoute(normalizedUrlPath))) + isDynamicRoute(matchedPath) && + !paramsResult.hasValidParams ) { const opts: Record = {} const routeParams = utils.getParamsFromRouteMatches( @@ -561,17 +553,29 @@ export default abstract class Server { if (opts.locale) { parsedUrl.query.__nextLocale = opts.locale } - paramsResult = utils.normalizeDynamicRouteParams(routeParams) + paramsResult = utils.normalizeDynamicRouteParams( + routeParams, + true + ) if (paramsResult.hasValidParams) { params = paramsResult.params } } + // handle the actual dynamic route name being requested + if ( + pageIsDynamic && + utils.defaultRouteMatches && + normalizedUrlPath === srcPathname && + !paramsResult.hasValidParams && + !utils.normalizeDynamicRouteParams({ ...params }, true) + .hasValidParams + ) { + params = utils.defaultRouteMatches + } + if (params) { - if (!paramsResult.hasValidParams) { - params = utils.normalizeDynamicRouteParams(params).params - } matchedPath = utils.interpolateDynamicPath(srcPathname, params) req.url = utils.interpolateDynamicPath(req.url!, params) } diff --git a/test/production/required-server-files.test.ts b/test/production/required-server-files.test.ts index 3e05971337220..a5fae289e7ceb 100644 --- a/test/production/required-server-files.test.ts +++ b/test/production/required-server-files.test.ts @@ -1029,6 +1029,23 @@ describe('should set-up next', () => { const html = await res.text() const $ = cheerio.load(html) expect($('#slug-page').text()).toBe('[slug] page') + expect(JSON.parse($('#router').text()).query).toEqual({ + slug: 'slug-1', + }) + + const res2 = await fetchViaHTTP(appPort, '/[slug]', undefined, { + headers: { + 'x-matched-path': '/[slug]', + }, + redirect: 'manual', + }) + + const html2 = await res2.text() + const $2 = cheerio.load(html2) + expect($2('#slug-page').text()).toBe('[slug] page') + expect(JSON.parse($2('#router').text()).query).toEqual({ + slug: '[slug]', + }) }) it('should have correct asPath on dynamic SSG page correctly', async () => {