Skip to content

Commit 4d2b7e5

Browse files
Marcus-Riseijjk
andauthored
Fix app render: escape segment value vercel#42626 (vercel#42823)
Fix: vercel#42398 relates to vercel#42626 (review) <!-- Thanks for opening a PR! Your contribution is much appreciated. To make sure your PR is handled as smoothly as possible we request that you follow the checklist sections below. Choose the right checklist for the change that you're making: --> ## Bug - [x] Related issues linked using `fixes #number` - [x] Integration tests added - [x] Errors have a helpful link attached, see `contributing.md` ## Feature - [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Documentation added - [ ] Telemetry added. In case of a feature if it's used or not. - [ ] Errors have a helpful link attached, see `contributing.md` ## Documentation / Examples - [ ] Make sure the linting passes by running `pnpm build && pnpm lint` - [ ] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md) Co-authored-by: JJ Kasper <[email protected]>
1 parent 22b16e1 commit 4d2b7e5

File tree

6 files changed

+98
-1
lines changed

6 files changed

+98
-1
lines changed

packages/next/server/app-render.tsx

+7-1
Original file line numberDiff line numberDiff line change
@@ -874,7 +874,13 @@ export async function renderToHTMLOrFlight(
874874
}
875875

876876
const key = segmentParam.param
877-
const value = pathParams[key]
877+
let value = pathParams[key]
878+
879+
if (Array.isArray(value)) {
880+
value = value.map((i) => encodeURIComponent(i))
881+
} else if (typeof value === 'string') {
882+
value = encodeURIComponent(value)
883+
}
878884

879885
if (!value) {
880886
// Handle case where optional catchall does not have a value, e.g. `/dashboard/[...slug]` when requesting `/dashboard`
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+
}
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+
}
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+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
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 { check } 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+
await check(() => browser.elementByCss('#page').text(), '/[slug]')
28+
} finally {
29+
if (browser) {
30+
await browser.close()
31+
}
32+
}
33+
})
34+
35+
it('should go to non-iso url', async () => {
36+
let browser: BrowserInterface
37+
38+
try {
39+
browser = await webdriver(next.appPort, '/')
40+
await browser.elementByCss('#to-non-iso').click()
41+
await check(() => browser.elementByCss('#page').text(), '/[slug]')
42+
} finally {
43+
if (browser) {
44+
await browser.close()
45+
}
46+
}
47+
})
48+
})
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)