Skip to content

Commit ff2d28c

Browse files
ijjktimneutkens
authored andcommitted
Add err.sh for invalid multi-match usage (vercel#9498)
* Adds err.sh for multi-match error * Fix missing apostrophe * Update regex to catch other param names * Add test for multi-match error * Update test/integration/invalid-multi-match/test/index.test.js
1 parent 874d3fd commit ff2d28c

File tree

5 files changed

+125
-1
lines changed

5 files changed

+125
-1
lines changed

errors/invalid-multi-match.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Invalid Multi-match
2+
3+
#### Why This Error Occurred
4+
5+
In one of your custom-routes you specified a multi-match `/:path*` and used it in your `destination` without adding the `*` in your `destination` e.g. `destination: '/another/:path'`
6+
7+
#### Possible Ways to Fix It
8+
9+
Add `*` to your usage of the multi-match param in your `destination`.
10+
11+
**Before**
12+
13+
```js
14+
{
15+
source: '/:path*',
16+
destination: '/another/:path'
17+
}
18+
```
19+
20+
**After**
21+
22+
```js
23+
{
24+
source: '/:path*',
25+
destination: '/another/:path*'
26+
}
27+
```

packages/next/next-server/server/next-server.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,20 @@ export default class Server {
412412
name: `${route.type} ${route.source} route`,
413413
fn: async (_req, res, params, _parsedUrl) => {
414414
let destinationCompiler = pathToRegexp.compile(route.destination)
415-
let newUrl = destinationCompiler(params)
415+
let newUrl
416+
417+
try {
418+
newUrl = destinationCompiler(params)
419+
} catch (err) {
420+
if (
421+
err.message.match(/Expected .*? to not repeat, but got array/)
422+
) {
423+
throw new Error(
424+
`To use a multi-match in the destination you must add \`*\` at the end of the param name to signify it should repeat. https://err.sh/zeit/next.js/invalid-multi-match`
425+
)
426+
}
427+
throw err
428+
}
416429

417430
if (route.type === 'redirect') {
418431
res.setHeader('Location', newUrl)
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
module.exports = {
2+
experimental: {
3+
rewrites() {
4+
return [
5+
{
6+
source: '/:hello*',
7+
destination: '/:hello',
8+
},
9+
]
10+
},
11+
},
12+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { useRouter } from 'next/router'
2+
3+
console.log('hello from hello.js')
4+
5+
const Page = () => {
6+
const { query } = useRouter()
7+
return (
8+
<>
9+
<h3>hello world</h3>
10+
<span>{JSON.stringify(query)}</span>
11+
</>
12+
)
13+
}
14+
15+
export default Page
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/* eslint-env jest */
2+
/* global jasmine */
3+
import { join } from 'path'
4+
import {
5+
launchApp,
6+
killApp,
7+
findPort,
8+
nextBuild,
9+
nextStart,
10+
renderViaHTTP,
11+
} from 'next-test-utils'
12+
13+
jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000 * 60 * 2
14+
15+
let appDir = join(__dirname, '..')
16+
let stderr = ''
17+
let appPort
18+
let app
19+
20+
const runTests = () => {
21+
it('should show error for invalid mulit-match', async () => {
22+
await renderViaHTTP(appPort, '/hello')
23+
expect(stderr).toContain(
24+
'To use a multi-match in the destination you must add'
25+
)
26+
expect(stderr).toContain('https://err.sh/zeit/next.js/invalid-multi-match')
27+
})
28+
}
29+
30+
describe('Custom routes', () => {
31+
describe('dev mode', () => {
32+
beforeAll(async () => {
33+
appPort = await findPort()
34+
app = await launchApp(appDir, appPort, {
35+
onStderr: msg => {
36+
stderr += msg
37+
},
38+
})
39+
})
40+
afterAll(() => killApp(app))
41+
runTests(true)
42+
})
43+
44+
describe('production mode', () => {
45+
beforeAll(async () => {
46+
await nextBuild(appDir)
47+
appPort = await findPort()
48+
app = await nextStart(appDir, appPort, {
49+
onStderr: msg => {
50+
stderr += msg
51+
},
52+
})
53+
})
54+
afterAll(() => killApp(app))
55+
runTests()
56+
})
57+
})

0 commit comments

Comments
 (0)