From 97587eb8e02e1f4d49914d05c7247baf10ef698d Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Mon, 18 May 2020 12:04:54 -0500 Subject: [PATCH] Correct multi-match behavior for queries and header values (#13017) --- .../next/next-server/server/next-server.ts | 6 +++- packages/next/next-server/server/router.ts | 5 ++- test/integration/custom-routes/next.config.js | 13 +++++++ .../custom-routes/test/index.test.js | 35 +++++++++++++++++++ 4 files changed, 57 insertions(+), 2 deletions(-) diff --git a/packages/next/next-server/server/next-server.ts b/packages/next/next-server/server/next-server.ts index b180d48e54..868fcef591 100644 --- a/packages/next/next-server/server/next-server.ts +++ b/packages/next/next-server/server/next-server.ts @@ -482,7 +482,11 @@ export default class Server { !parsedDestination.pathname || !parsedDestination.pathname.startsWith('/') ) { - return compilePathToRegex(value, { validate: false })(params) + // the value needs to start with a forward-slash to be compiled + // correctly + return compilePathToRegex(`/${value}`, { validate: false })( + params + ).substr(1) } return formatUrl(parsedDestination) } diff --git a/packages/next/next-server/server/router.ts b/packages/next/next-server/server/router.ts index 89ccc26231..0bab91100d 100644 --- a/packages/next/next-server/server/router.ts +++ b/packages/next/next-server/server/router.ts @@ -58,8 +58,11 @@ export const prepareDestination = ( for (const [key, strOrArray] of Object.entries(destQuery)) { let value = Array.isArray(strOrArray) ? strOrArray[0] : strOrArray if (value) { + // the value needs to start with a forward-slash to be compiled + // correctly + value = `/${value}` const queryCompiler = compilePathToRegex(value, { validate: false }) - value = queryCompiler(params) + value = queryCompiler(params).substr(1) } destQuery[key] = value } diff --git a/test/integration/custom-routes/next.config.js b/test/integration/custom-routes/next.config.js index 0e9b80297c..bc250413df 100644 --- a/test/integration/custom-routes/next.config.js +++ b/test/integration/custom-routes/next.config.js @@ -91,6 +91,10 @@ module.exports = { source: '/catchall-rewrite/:path*', destination: '/with-params', }, + { + source: '/catchall-query/:path*', + destination: '/with-params?another=:path*', + }, ] }, async redirects() { @@ -283,6 +287,15 @@ module.exports = { }, ], }, + { + source: '/catchall-header/:path*', + headers: [ + { + key: 'x-value', + value: ':path*', + }, + ], + }, ] }, }, diff --git a/test/integration/custom-routes/test/index.test.js b/test/integration/custom-routes/test/index.test.js index a3b14d3c1c..0df5a2f29a 100644 --- a/test/integration/custom-routes/test/index.test.js +++ b/test/integration/custom-routes/test/index.test.js @@ -178,6 +178,22 @@ const runTests = (isDev = false) => { }) }) + it('should have correct query for catchall rewrite', async () => { + const html = await renderViaHTTP(appPort, '/catchall-query/hello/world?a=b') + const $ = cheerio.load(html) + expect(JSON.parse($('#__NEXT_DATA__').html()).query).toEqual({ + a: 'b', + another: 'hello/world', + path: ['hello', 'world'], + }) + }) + + it('should have correct query for catchall rewrite', async () => { + const res = await fetchViaHTTP(appPort, '/catchall-header/hello/world?a=b') + const headerValue = res.headers.get('x-value') + expect(headerValue).toBe('hello/world') + }) + it('should allow params in query for redirect', async () => { const res = await fetchViaHTTP( appPort, @@ -716,6 +732,18 @@ const runTests = (isDev = false) => { regex: normalizeRegEx('^\\/named-pattern(?:\\/(.*))$'), source: '/named-pattern/:path(.*)', }, + { + headers: [ + { + key: 'x-value', + value: ':path*', + }, + ], + regex: normalizeRegEx( + '^\\/catchall-header(?:\\/((?:[^\\/]+?)(?:\\/(?:[^\\/]+?))*))?$' + ), + source: '/catchall-header/:path*', + }, ], rewrites: [ { @@ -840,6 +868,13 @@ const runTests = (isDev = false) => { ), source: '/catchall-rewrite/:path*', }, + { + destination: '/with-params?another=:path*', + regex: normalizeRegEx( + '^\\/catchall-query(?:\\/((?:[^\\/]+?)(?:\\/(?:[^\\/]+?))*))?$' + ), + source: '/catchall-query/:path*', + }, ], dynamicRoutes: [ { -- GitLab