Skip to content

Commit 49fd975

Browse files
committed
#42398 fix(app-render): escape segment value
1 parent 0e8f241 commit 49fd975

File tree

6 files changed

+108
-1
lines changed

6 files changed

+108
-1
lines changed

packages/next/server/app-render.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -855,7 +855,13 @@ export async function renderToHTMLOrFlight(
855855
}
856856

857857
const key = segmentParam.param
858-
const value = pathParams[key]
858+
let value = pathParams[key]
859+
860+
if (Array.isArray(value)) {
861+
value = value.map((i) => encodeURIComponent(i))
862+
} else if (typeof value === 'string') {
863+
value = encodeURIComponent(value)
864+
}
859865

860866
if (!value) {
861867
// Handle case where optional catchall does not have a value, e.g. `/dashboard/[...slug]` when requesting `/dashboard`
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
export default function Slug(props) {
2+
return (
3+
<>
4+
<p id="page">/[slug]</p>
5+
<p id="props">{JSON.stringify(props)}</p>
6+
</>
7+
)
8+
}
9+
10+
export function generateStaticParams() {
11+
return [{ slug: 'iso-url' }, { slug: 'кириллица' }]
12+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export default function Layout({ children }) {
2+
return (
3+
<html>
4+
<body>{children}</body>
5+
</html>
6+
)
7+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import Link from 'next/link'
2+
3+
export default function Page(props) {
4+
return (
5+
<>
6+
<p id="page">index</p>
7+
<p id="props">{JSON.stringify(props)}</p>
8+
<Link href="/iso-url" id="to-iso">
9+
/iso-url
10+
</Link>
11+
<br />
12+
<Link href="/кириллица" id="to-non-iso">
13+
/кириллица
14+
</Link>
15+
<br />
16+
</>
17+
)
18+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { createNext, FileRef } from 'e2e-utils'
2+
import { NextInstance } from 'test/lib/next-modes/base'
3+
import { join } from 'path'
4+
import { BrowserInterface } from '../../lib/browsers/base'
5+
import webdriver from 'next-webdriver'
6+
import { waitFor } from 'next-test-utils'
7+
8+
describe('app-dir-prefetch-non-iso-url', () => {
9+
let next: NextInstance
10+
11+
beforeAll(async () => {
12+
next = await createNext({
13+
files: {
14+
'next.config.js': new FileRef(join(__dirname, 'next.config.js')),
15+
app: new FileRef(join(__dirname, 'app')),
16+
},
17+
})
18+
})
19+
afterAll(() => next.destroy())
20+
21+
it('should go to iso url', async () => {
22+
let browser: BrowserInterface
23+
24+
try {
25+
browser = await webdriver(next.appPort, '/')
26+
await browser.elementByCss('#to-iso').click()
27+
28+
const text = await browser.elementByCss('#page').text()
29+
30+
await waitFor(3000)
31+
32+
expect(text).toBe('/[slug]')
33+
} finally {
34+
if (browser) {
35+
await browser.close()
36+
}
37+
}
38+
})
39+
40+
it('should go to non-iso url', async () => {
41+
let browser: BrowserInterface
42+
43+
try {
44+
browser = await webdriver(next.appPort, '/')
45+
await browser.elementByCss('#to-non-iso').click()
46+
47+
const text = await browser.elementByCss('#page').text()
48+
49+
await waitFor(3000)
50+
51+
expect(text).toBe('/[slug]')
52+
} finally {
53+
if (browser) {
54+
await browser.close()
55+
}
56+
}
57+
})
58+
})
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/** @type {import("next").NextConfig} */
2+
const nextConfig = {
3+
experimental: { appDir: true },
4+
}
5+
6+
module.exports = nextConfig

0 commit comments

Comments
 (0)