mirror of
https://github.com/cloudflare/vinext.git
synced 2026-05-09 08:25:34 +02:00
[PR #1086] [MERGED] refactor(routing+server): unify route-match preamble and middleware header merge #1081
Labels
No labels
enhancement
enhancement
good first issue
help wanted
nextjs-tracking
nextjs-tracking
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
starred/vinext#1081
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/cloudflare/vinext/pull/1086
Author: @james-elicx
Created: 5/5/2026
Status: ✅ Merged
Merged: 5/5/2026
Merged by: @james-elicx
Base:
main← Head:refactor/unify-pages-app-shared-utilities📝 Commits (1)
040f103refactor(routing): unify route-match preamble across pages and app routers📊 Changes
3 files changed (+65 additions, -41 deletions)
View changed files
📝
packages/vinext/src/routing/app-router.ts(+3 -20)📝
packages/vinext/src/routing/pages-router.ts(+4 -21)➕
packages/vinext/src/routing/route-matching.ts(+58 -0)📄 Description
Summary
Part A — route-matching preamble (shipped)
Both Pages Router (
matchRouteinrouting/pages-router.ts) and App Router (matchAppRouteinrouting/app-router.ts) had nearly identical preambles aroundtrieMatch: strip query, trailing-slash normalize, runnormalizePathnameForRouteMatch, split into url parts, then look up via a per-routes-arrayWeakMaptrie cache. Each side also had its owngetOrBuildTriehelper.Extracted into a new
routing/route-matching.ts:matchRouteWithTrie<R extends { patternParts: string[] }>(url, routes, cache)— generic over the route shape; bothRoute(Pages) andAppRoutesatisfy the constraint.createRouteTrieCache<R>()— each router still owns its own cache instance, so different route shapes don't share a slot.matchRouteandmatchAppRouteare now thin wrappers; the public API is unchanged.Part B — pages middleware header merge (deferred)
Originally planned to migrate
applyGsspHeaders(inserver/pages-page-response.ts) to the sharedmergeMiddlewareResponseHeadershelper. After reading both sides carefully, the semantics are non-trivially divergent:applyGsspHeadersreads fromPagesGsspResponse.getHeaders(), which returns Node-styleOutgoingHttpHeaders(Record<string, string | number | boolean | string[]>). The shared helper iterates a WebHeadersobject.applyGsspHeadersjoins non-cookiestring[]values with", "and usesset(). The shared helper has no such path.applyGsspHeadersdoes not Vary-merge (it would,-join +setif Vary ever arrived as an array, which collapses RFC 9110*semantics differently frommergeVaryHeader).applyGsspHeadersonly appends Set-Cookie when the value is an array; a singular string falls through toset(). The shared helper always appends.Content-Type: text/htmland returnsstatusCode.Collapsing those into the shared helper without breaking subtle production semantics needs either a Node-headers adapter or a meaningful API extension. Per the conservative-parity directive, deferring as a separate PR rather than risking silent behavior change here.
Pure refactor; no behavior change. Follow-up to #1058.
Files
packages/vinext/src/routing/route-matching.ts(new) — genericmatchRouteWithTrie+createRouteTrieCache.packages/vinext/src/routing/pages-router.ts—matchRoutedelegates to shared helper.packages/vinext/src/routing/app-router.ts—matchAppRoutedelegates to shared helper.Test plan
pnpm vp test run tests/app-router.test.ts tests/routing.test.ts tests/route-trie.test.ts— 481 passed.pnpm vp test run tests/pages-router.test.ts— 200 passed (one pre-existingafterAllteardown timeout in theallowedDevOriginssuite, unrelated to this change; reproduces onmain).pnpm fmt --writeclean.pnpm knipclean.🤖 Generated with Claude Code
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.