8000 Fix app render: escape segment value #42626 (#42823) · vercel/next.js@4d2b7e5 · GitHub
[go: up one dir, main page]

Skip to content

Commit 4d2b7e5

Browse files
Marcus-Riseijjk
andauthored
Fix app render: escape segment value #42626 (#42823)
Fix: #42398 relates to #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 <jj@jjsweb.site>
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

Lines changed: 7 additions & 1 deletion
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`
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: 48 additions & 0 deletions
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+
})
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)
0