Correct multi-match behavior for queries and header values (#13017)

This commit is contained in:
JJ Kasper 2020-05-18 12:04:54 -05:00 committed by GitHub
parent dd264f582f
commit 97587eb8e0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 57 additions and 2 deletions

View file

@ -482,7 +482,11 @@ export default class Server {
!parsedDestination.pathname || !parsedDestination.pathname ||
!parsedDestination.pathname.startsWith('/') !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) return formatUrl(parsedDestination)
} }

View file

@ -58,8 +58,11 @@ export const prepareDestination = (
for (const [key, strOrArray] of Object.entries(destQuery)) { for (const [key, strOrArray] of Object.entries(destQuery)) {
let value = Array.isArray(strOrArray) ? strOrArray[0] : strOrArray let value = Array.isArray(strOrArray) ? strOrArray[0] : strOrArray
if (value) { if (value) {
// the value needs to start with a forward-slash to be compiled
// correctly
value = `/${value}`
const queryCompiler = compilePathToRegex(value, { validate: false }) const queryCompiler = compilePathToRegex(value, { validate: false })
value = queryCompiler(params) value = queryCompiler(params).substr(1)
} }
destQuery[key] = value destQuery[key] = value
} }

View file

@ -91,6 +91,10 @@ module.exports = {
source: '/catchall-rewrite/:path*', source: '/catchall-rewrite/:path*',
destination: '/with-params', destination: '/with-params',
}, },
{
source: '/catchall-query/:path*',
destination: '/with-params?another=:path*',
},
] ]
}, },
async redirects() { async redirects() {
@ -283,6 +287,15 @@ module.exports = {
}, },
], ],
}, },
{
source: '/catchall-header/:path*',
headers: [
{
key: 'x-value',
value: ':path*',
},
],
},
] ]
}, },
}, },

View file

@ -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 () => { it('should allow params in query for redirect', async () => {
const res = await fetchViaHTTP( const res = await fetchViaHTTP(
appPort, appPort,
@ -716,6 +732,18 @@ const runTests = (isDev = false) => {
regex: normalizeRegEx('^\\/named-pattern(?:\\/(.*))$'), regex: normalizeRegEx('^\\/named-pattern(?:\\/(.*))$'),
source: '/named-pattern/:path(.*)', source: '/named-pattern/:path(.*)',
}, },
{
headers: [
{
key: 'x-value',
value: ':path*',
},
],
regex: normalizeRegEx(
'^\\/catchall-header(?:\\/((?:[^\\/]+?)(?:\\/(?:[^\\/]+?))*))?$'
),
source: '/catchall-header/:path*',
},
], ],
rewrites: [ rewrites: [
{ {
@ -840,6 +868,13 @@ const runTests = (isDev = false) => {
), ),
source: '/catchall-rewrite/:path*', source: '/catchall-rewrite/:path*',
}, },
{
destination: '/with-params?another=:path*',
regex: normalizeRegEx(
'^\\/catchall-query(?:\\/((?:[^\\/]+?)(?:\\/(?:[^\\/]+?))*))?$'
),
source: '/catchall-query/:path*',
},
], ],
dynamicRoutes: [ dynamicRoutes: [
{ {