Skip to content

Commit f9b5a5a

Browse files
fix(start): support SSR for non-Latin character route paths (#4611)
1 parent 4124583 commit f9b5a5a

File tree

7 files changed

+112
-1
lines changed

7 files changed

+112
-1
lines changed

e2e/react-router/basic-file-based/src/routeTree.gen.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import { createFileRoute } from '@tanstack/react-router'
1212

1313
import { Route as rootRouteImport } from './routes/__root'
14+
import { Route as Char45824Char54620Char48124Char44397RouteImport } from './routes/대한민국'
1415
import { Route as PostsRouteImport } from './routes/posts'
1516
import { Route as EditingBRouteImport } from './routes/editing-b'
1617
import { Route as EditingARouteImport } from './routes/editing-a'
@@ -58,6 +59,12 @@ const groupRoute = groupRouteImport.update({
5859
id: '/(group)',
5960
getParentRoute: () => rootRouteImport,
6061
} as any)
62+
const Char45824Char54620Char48124Char44397Route =
63+
Char45824Char54620Char48124Char44397RouteImport.update({
64+
id: '/대한민국',
65+
path: '/대한민국',
66+
getParentRoute: () => rootRouteImport,
67+
} as any)
6168
const PostsRoute = PostsRouteImport.update({
6269
id: '/posts',
6370
path: '/posts',
@@ -272,6 +279,7 @@ export interface FileRoutesByFullPath {
272279
'/editing-a': typeof EditingARoute
273280
'/editing-b': typeof EditingBRoute
274281
'/posts': typeof PostsRouteWithChildren
282+
'/대한민국': typeof Char45824Char54620Char48124Char44397Route
275283
'/onlyrouteinside': typeof anotherGroupOnlyrouteinsideRoute
276284
'/inside': typeof groupInsideRoute
277285
'/lazyinside': typeof groupLazyinsideRoute
@@ -309,6 +317,7 @@ export interface FileRoutesByTo {
309317
'/anchor': typeof AnchorRoute
310318
'/editing-a': typeof EditingARoute
311319
'/editing-b': typeof EditingBRoute
320+
'/대한민국': typeof Char45824Char54620Char48124Char44397Route
312321
'/onlyrouteinside': typeof anotherGroupOnlyrouteinsideRoute
313322
'/inside': typeof groupInsideRoute
314323
'/lazyinside': typeof groupLazyinsideRoute
@@ -349,6 +358,7 @@ export interface FileRoutesById {
349358
'/editing-a': typeof EditingARoute
350359
'/editing-b': typeof EditingBRoute
351360
'/posts': typeof PostsRouteWithChildren
361+
'/대한민국': typeof Char45824Char54620Char48124Char44397Route
352362
'/(another-group)/onlyrouteinside': typeof anotherGroupOnlyrouteinsideRoute
353363
'/(group)': typeof groupRouteWithChildren
354364
'/(group)/_layout': typeof groupLayoutRouteWithChildren
@@ -393,6 +403,7 @@ export interface FileRouteTypes {
393403
| '/editing-a'
394404
| '/editing-b'
395405
| '/posts'
406+
| '/대한민국'
396407
| '/onlyrouteinside'
397408
| '/inside'
398409
| '/lazyinside'
@@ -430,6 +441,7 @@ export interface FileRouteTypes {
430441
| '/anchor'
431442
| '/editing-a'
432443
| '/editing-b'
444+
| '/대한민국'
433445
| '/onlyrouteinside'
434446
| '/inside'
435447
| '/lazyinside'
@@ -469,6 +481,7 @@ export interface FileRouteTypes {
469481
| '/editing-a'
470482
| '/editing-b'
471483
| '/posts'
484+
| '/대한민국'
472485
| '/(another-group)/onlyrouteinside'
473486
| '/(group)'
474487
| '/(group)/_layout'
@@ -513,6 +526,7 @@ export interface RootRouteChildren {
513526
EditingARoute: typeof EditingARoute
514527
EditingBRoute: typeof EditingBRoute
515528
PostsRoute: typeof PostsRouteWithChildren
529+
Char45824Char54620Char48124Char44397Route: typeof Char45824Char54620Char48124Char44397Route
516530
anotherGroupOnlyrouteinsideRoute: typeof anotherGroupOnlyrouteinsideRoute
517531
groupRoute: typeof groupRouteWithChildren
518532
RedirectTargetRoute: typeof RedirectTargetRouteWithChildren
@@ -543,6 +557,13 @@ declare module '@tanstack/react-router' {
543557
preLoaderRoute: typeof groupRouteImport
544558
parentRoute: typeof rootRouteImport
545559
}
560+
'/대한민국': {
561+
id: '/대한민국'
562+
path: '/대한민국'
563+
fullPath: '/대한민국'
564+
preLoaderRoute: typeof Char45824Char54620Char48124Char44397RouteImport
565+
parentRoute: typeof rootRouteImport
566+
}
546567
'/posts': {
547568
id: '/posts'
548569
path: '/posts'
@@ -928,6 +949,8 @@ const rootRouteChildren: RootRouteChildren = {
928949
EditingARoute: EditingARoute,
929950
EditingBRoute: EditingBRoute,
930951
PostsRoute: PostsRouteWithChildren,
952+
Char45824Char54620Char48124Char44397Route:
953+
Char45824Char54620Char48124Char44397Route,
931954
anotherGroupOnlyrouteinsideRoute: anotherGroupOnlyrouteinsideRoute,
932955
groupRoute: groupRouteWithChildren,
933956
RedirectTargetRoute: RedirectTargetRouteWithChildren,
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { createFileRoute } from '@tanstack/react-router'
2+
3+
export const Route = createFileRoute('/대한민국')({
4+
component: RouteComponent,
5+
})
6+
7+
function RouteComponent() {
8+
return <div>Hello "/대한민국"!</div>
9+
}

e2e/react-router/basic-file-based/tests/params.spec.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,3 +202,13 @@ test.describe('params operations + prefix/suffix', () => {
202202
})
203203
})
204204
})
205+
206+
test.describe('Unicode route rendering', () => {
207+
test('should render non-latin route correctly', async ({ page, baseURL }) => {
208+
await page.goto('/대한민국')
209+
210+
await expect(page.locator('body')).toContainText('Hello "/대한민국"!')
211+
212+
expect(page.url()).toBe(`${baseURL}/%EB%8C%80%ED%95%9C%EB%AF%BC%EA%B5%AD`)
213+
})
214+
})

e2e/react-start/basic/src/routeTree.gen.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import type {
1717
import { createServerRootRoute } from '@tanstack/react-start/server'
1818

1919
import { Route as rootRouteImport } from './routes/__root'
20+
import { Route as Char45824Char54620Char48124Char44397RouteImport } from './routes/대한민국'
2021
import { Route as UsersRouteImport } from './routes/users'
2122
import { Route as StreamRouteImport } from './routes/stream'
2223
import { Route as ScriptsRouteImport } from './routes/scripts'
@@ -58,6 +59,12 @@ import { ServerRoute as ApiUsersIdServerRouteImport } from './routes/api/users.$
5859
const FooBarQuxRouteImport = createFileRoute('/foo/$bar/$qux')()
5960
const rootServerRouteImport = createServerRootRoute()
6061

62+
const Char45824Char54620Char48124Char44397Route =
63+
Char45824Char54620Char48124Char44397RouteImport.update({
64+
id: '/대한민국',
65+
path: '/대한민국',
66+
getParentRoute: () => rootRouteImport,
67+
} as any)
6168
const UsersRoute = UsersRouteImport.update({
6269
id: '/users',
6370
path: '/users',
@@ -262,6 +269,7 @@ export interface FileRoutesByFullPath {
262269
'/scripts': typeof ScriptsRoute
263270
'/stream': typeof StreamRoute
264271
'/users': typeof UsersRouteWithChildren
272+
'/대한민국': typeof Char45824Char54620Char48124Char44397Route
265273
'/not-found/via-beforeLoad': typeof NotFoundViaBeforeLoadRoute
266274
'/not-found/via-loader': typeof NotFoundViaLoaderRoute
267275
'/posts/$postId': typeof PostsPostIdRoute
@@ -293,6 +301,7 @@ export interface FileRoutesByTo {
293301
'/links': typeof LinksRoute
294302
'/scripts': typeof ScriptsRoute
295303
'/stream': typeof StreamRoute
304+
'/대한민국': typeof Char45824Char54620Char48124Char44397Route
296305
'/not-found/via-beforeLoad': typeof NotFoundViaBeforeLoadRoute
297306
'/not-found/via-loader': typeof NotFoundViaLoaderRoute
298307
'/posts/$postId': typeof PostsPostIdRoute
@@ -328,6 +337,7 @@ export interface FileRoutesById {
328337
'/scripts': typeof ScriptsRoute
329338
'/stream': typeof StreamRoute
330339
'/users': typeof UsersRouteWithChildren
340+
'/대한민국': typeof Char45824Char54620Char48124Char44397Route
331341
'/_layout/_layout-2': typeof LayoutLayout2RouteWithChildren
332342
'/not-found/via-beforeLoad': typeof NotFoundViaBeforeLoadRoute
333343
'/not-found/via-loader': typeof NotFoundViaLoaderRoute
@@ -367,6 +377,7 @@ export interface FileRouteTypes {
367377
| '/scripts'
368378
| '/stream'
369379
| '/users'
380+
| '/대한민국'
370381
| '/not-found/via-beforeLoad'
371382
| '/not-found/via-loader'
372383
| '/posts/$postId'
@@ -398,6 +409,7 @@ export interface FileRouteTypes {
398409
| '/links'
399410
| '/scripts'
400411
| '/stream'
412+
| '/대한민국'
401413
| '/not-found/via-beforeLoad'
402414
| '/not-found/via-loader'
403415
| '/posts/$postId'
@@ -432,6 +444,7 @@ export interface FileRouteTypes {
432444
| '/scripts'
433445
| '/stream'
434446
| '/users'
447+
| '/대한민국'
435448
| '/_layout/_layout-2'
436449
| '/not-found/via-beforeLoad'
437450
| '/not-found/via-loader'
@@ -471,6 +484,7 @@ export interface RootRouteChildren {
471484
ScriptsRoute: typeof ScriptsRoute
472485
StreamRoute: typeof StreamRoute
473486
UsersRoute: typeof UsersRouteWithChildren
487+
Char45824Char54620Char48124Char44397Route: typeof Char45824Char54620Char48124Char44397Route
474488
RedirectTargetRoute: typeof RedirectTargetRouteWithChildren
475489
RedirectIndexRoute: typeof RedirectIndexRoute
476490
PostsPostIdDeepRoute: typeof PostsPostIdDeepRoute
@@ -573,6 +587,13 @@ declare module '@tanstack/react-router' {
573587
preLoaderRoute: typeof UsersRouteImport
574588
parentRoute: typeof rootRouteImport
575589
}
590+
'/대한민국': {
591+
id: '/대한민국'
592+
path: '/대한민국'
593+
fullPath: '/대한민국'
594+
preLoaderRoute: typeof Char45824Char54620Char48124Char44397RouteImport
595+
parentRoute: typeof rootRouteImport
596+
}
576597
'/_layout/_layout-2': {
577598
id: '/_layout/_layout-2'
578599
path: ''
@@ -843,6 +864,13 @@ declare module '@tanstack/react-start/server' {
843864
preLoaderRoute: unknown
844865
parentRoute: typeof rootServerRouteImport
845866
}
867+
'/대한민국': {
868+
id: '/대한민국'
869+
path: '/대한민국'
870+
fullPath: '/대한민국'
871+
preLoaderRoute: unknown
872+
parentRoute: typeof rootServerRouteImport
873+
}
846874
'/_layout/_layout-2': {
847875
id: '/_layout/_layout-2'
848876
path: ''
@@ -1205,6 +1233,23 @@ declare module './routes/users' {
12051233
unknown
12061234
>
12071235
}
1236+
declare module './routes/대한민국' {
1237+
const createFileRoute: CreateFileRoute<
1238+
'/대한민국',
1239+
FileRoutesByPath['/대한민국']['parentRoute'],
1240+
FileRoutesByPath['/대한민국']['id'],
1241+
FileRoutesByPath['/대한민국']['path'],
1242+
FileRoutesByPath['/대한민국']['fullPath']
1243+
>
1244+
1245+
const createServerFileRoute: CreateServerFileRoute<
1246+
ServerFileRoutesByPath['/대한민국']['parentRoute'],
1247+
ServerFileRoutesByPath['/대한민국']['id'],
1248+
ServerFileRoutesByPath['/대한민국']['path'],
1249+
ServerFileRoutesByPath['/대한민국']['fullPath'],
1250+
unknown
1251+
>
1252+
}
12081253
declare module './routes/_layout/_layout-2' {
12091254
const createFileRoute: CreateFileRoute<
12101255
'/_layout/_layout-2',
@@ -1818,6 +1863,8 @@ const rootRouteChildren: RootRouteChildren = {
18181863
ScriptsRoute: ScriptsRoute,
18191864
StreamRoute: StreamRoute,
18201865
UsersRoute: UsersRouteWithChildren,
1866+
Char45824Char54620Char48124Char44397Route:
1867+
Char45824Char54620Char48124Char44397Route,
18211868
RedirectTargetRoute: RedirectTargetRouteWithChildren,
18221869
RedirectIndexRoute: RedirectIndexRoute,
18231870
PostsPostIdDeepRoute: PostsPostIdDeepRoute,
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export const Route = createFileRoute({
2+
component: RouteComponent,
3+
})
4+
5+
function RouteComponent() {
6+
return <div>Hello "/대한민국"!</div>
7+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { expect, test } from '@playwright/test'
2+
3+
test.beforeEach(async ({ page }) => {
4+
await page.goto('/')
5+
})
6+
7+
test.describe('Unicode route rendering', () => {
8+
test('should render non-latin route correctly', async ({ page, baseURL }) => {
9+
await page.goto('/대한민국')
10+
11+
await expect(page.locator('body')).toContainText('Hello "/대한민국"!')
12+
13+
expect(page.url()).toBe(`${baseURL}/%EB%8C%80%ED%95%9C%EB%AF%BC%EA%B5%AD`)
14+
})
15+
})

packages/start-server-core/src/createStartHandler.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ export function createStartHandler<TRouter extends AnyRouter>({
110110
}
111111

112112
const url = new URL(request.url)
113-
const href = url.href.replace(url.origin, '')
113+
const href = decodeURIComponent(url.href.replace(url.origin, ''))
114114

115115
const APP_BASE = process.env.TSS_APP_BASE || '/'
116116

0 commit comments

Comments
 (0)