[PR #456] [MERGED] fix: Preserve encoded path delimiters in route discovery and matching #584

Closed
opened 2026-05-06 13:08:54 +02:00 by BreizhHardware · 0 comments

📋 Pull Request Information

Original PR: https://github.com/cloudflare/vinext/pull/456
Author: @JaredStowell
Created: 3/11/2026
Status: Merged
Merged: 3/11/2026
Merged by: @james-elicx

Base: mainHead: jstowell/fix-encoded-slash-route-segments


📝 Commits (6)

  • 06802af Fix App Router decoding collision
  • 847405f Fix App Router path decoding
  • 6150327 Merge remote-tracking branch 'origin/main' into jstowell/fix-encoded-slash-route-segments
  • 8f7874e Address bonk review: codegen safe segment decode, static serving, nits
  • eb0ab60 fix: add codegen strict normalizer, use it at 400-returning call sites
  • c7c847f Merge remote-tracking branch 'origin/main' into jstowell/fix-encoded-slash-route-segments

📊 Changes

13 files changed (+483 additions, -52 deletions)

View changed files

📝 packages/vinext/src/entries/app-rsc-entry.ts (+6 -4)
📝 packages/vinext/src/entries/pages-server-entry.ts (+3 -1)
📝 packages/vinext/src/index.ts (+2 -1)
📝 packages/vinext/src/routing/app-router.ts (+3 -11)
📝 packages/vinext/src/routing/pages-router.ts (+3 -7)
📝 packages/vinext/src/routing/utils.ts (+52 -0)
📝 packages/vinext/src/server/middleware-codegen.ts (+40 -0)
📝 packages/vinext/src/server/middleware.ts (+2 -1)
📝 packages/vinext/src/server/prod-server.ts (+3 -2)
📝 tests/__snapshots__/entry-templates.test.ts.snap (+207 -25)
📝 tests/app-router.test.ts (+20 -0)
📝 tests/pages-router.test.ts (+99 -0)
📝 tests/routing.test.ts (+43 -0)

📄 Description

Preserve encoded path delimiters throughout route discovery, route matching, and live request handling.

Previously, vinext decoded entire pathnames with decodeURIComponent in several routing paths. That caused encoded delimiters like %2F to collapse into real path separators, so routes such as app/a%2Fb/page.tsx and app/a/b/page.tsx could collide during discovery or be misrouted at runtime.

This change switches vinext to segment-wise pathname normalization that preserves encoded path delimiters while still decoding safe escapes.

What changed

  • Add shared pathname normalization helpers for delimiter-preserving route matching
  • Update App Router and Pages Router discovery/matcher logic to use segment-wise decoding
  • Update App Router dev/prod request handling to avoid whole-path decoding before route matching
  • Update Pages Router dev/prod request handling to avoid whole-path decoding before route matching
  • Update middleware matching and generated entry code to use the same normalization behavior
  • Add regression coverage for helper-level matching and end-to-end dev/prod runtime behavior

Behavior

  • %5F still decodes to _
  • %2F, %23, %3F, and %5C remain encoded within a segment
  • Malformed percent-encoded pathnames still return 400 instead of crashing

Why

This fixes real route collisions and dev/prod mismatches around encoded slashes, and keeps request-time routing in parity with the new discovery logic instead of only fixing the shared helpers.

Testing

  • pnpm test tests/routing.test.ts tests/app-router.test.ts tests/pages-router.test.ts tests/entry-templates.test.ts
  • pnpm run fmt
  • pnpm run typecheck
  • pnpm test

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/cloudflare/vinext/pull/456 **Author:** [@JaredStowell](https://github.com/JaredStowell) **Created:** 3/11/2026 **Status:** ✅ Merged **Merged:** 3/11/2026 **Merged by:** [@james-elicx](https://github.com/james-elicx) **Base:** `main` ← **Head:** `jstowell/fix-encoded-slash-route-segments` --- ### 📝 Commits (6) - [`06802af`](https://github.com/cloudflare/vinext/commit/06802af3326d20b71eae6f1465a4c0434f910df8) Fix App Router decoding collision - [`847405f`](https://github.com/cloudflare/vinext/commit/847405fa40375ea05911a88ee7fcbccbfeb562ea) Fix App Router path decoding - [`6150327`](https://github.com/cloudflare/vinext/commit/6150327089643cfd1615d0ed5f40d7a00056e86e) Merge remote-tracking branch 'origin/main' into jstowell/fix-encoded-slash-route-segments - [`8f7874e`](https://github.com/cloudflare/vinext/commit/8f7874e6097087cafafa67b35383619024ebf1cf) Address bonk review: codegen safe segment decode, static serving, nits - [`eb0ab60`](https://github.com/cloudflare/vinext/commit/eb0ab60d77a06378842f00cfbdb2f988ee93642b) fix: add codegen strict normalizer, use it at 400-returning call sites - [`c7c847f`](https://github.com/cloudflare/vinext/commit/c7c847f10c241c16efed41f416348ba41528ffdf) Merge remote-tracking branch 'origin/main' into jstowell/fix-encoded-slash-route-segments ### 📊 Changes **13 files changed** (+483 additions, -52 deletions) <details> <summary>View changed files</summary> 📝 `packages/vinext/src/entries/app-rsc-entry.ts` (+6 -4) 📝 `packages/vinext/src/entries/pages-server-entry.ts` (+3 -1) 📝 `packages/vinext/src/index.ts` (+2 -1) 📝 `packages/vinext/src/routing/app-router.ts` (+3 -11) 📝 `packages/vinext/src/routing/pages-router.ts` (+3 -7) 📝 `packages/vinext/src/routing/utils.ts` (+52 -0) 📝 `packages/vinext/src/server/middleware-codegen.ts` (+40 -0) 📝 `packages/vinext/src/server/middleware.ts` (+2 -1) 📝 `packages/vinext/src/server/prod-server.ts` (+3 -2) 📝 `tests/__snapshots__/entry-templates.test.ts.snap` (+207 -25) 📝 `tests/app-router.test.ts` (+20 -0) 📝 `tests/pages-router.test.ts` (+99 -0) 📝 `tests/routing.test.ts` (+43 -0) </details> ### 📄 Description Preserve encoded path delimiters throughout route discovery, route matching, and live request handling. Previously, vinext decoded entire pathnames with `decodeURIComponent` in several routing paths. That caused encoded delimiters like `%2F` to collapse into real path separators, so routes such as `app/a%2Fb/page.tsx` and `app/a/b/page.tsx` could collide during discovery or be misrouted at runtime. This change switches vinext to segment-wise pathname normalization that preserves encoded path delimiters while still decoding safe escapes. ## What changed - Add shared pathname normalization helpers for delimiter-preserving route matching - Update App Router and Pages Router discovery/matcher logic to use segment-wise decoding - Update App Router dev/prod request handling to avoid whole-path decoding before route matching - Update Pages Router dev/prod request handling to avoid whole-path decoding before route matching - Update middleware matching and generated entry code to use the same normalization behavior - Add regression coverage for helper-level matching and end-to-end dev/prod runtime behavior ## Behavior - `%5F` still decodes to `_` - `%2F`, `%23`, `%3F`, and `%5C` remain encoded within a segment - Malformed percent-encoded pathnames still return `400` instead of crashing ## Why This fixes real route collisions and dev/prod mismatches around encoded slashes, and keeps request-time routing in parity with the new discovery logic instead of only fixing the shared helpers. ## Testing - `pnpm test tests/routing.test.ts tests/app-router.test.ts tests/pages-router.test.ts tests/entry-templates.test.ts` - `pnpm run fmt` - `pnpm run typecheck` - `pnpm test` --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
BreizhHardware 2026-05-06 13:08:54 +02:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/vinext#584
No description provided.