[PR #422] [MERGED] fix: preserve repeated route and query params in rewrites and redirects #560

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

📋 Pull Request Information

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

Base: mainHead: jstowell/fix-config-matchers-repeated-params


📝 Commits (3)

📊 Changes

7 files changed (+248 additions, -23 deletions)

View changed files

📝 packages/vinext/src/config/config-matchers.ts (+49 -22)
📝 tests/__snapshots__/entry-templates.test.ts.snap (+1 -1)
📝 tests/app-router.test.ts (+32 -0)
📝 tests/fixtures/app-basic/next.config.ts (+11 -0)
📝 tests/fixtures/pages-basic/next.config.mjs (+9 -0)
📝 tests/pages-router.test.ts (+26 -0)
📝 tests/shims.test.ts (+120 -0)

📄 Description

Fix two next.config matcher bugs in config-matchers.ts:

  1. Redirects and rewrites only replaced the first occurrence of a route param in the destination.
    • Example: /post/:id -> /api/:id/:id produced /api/123/:id
  2. External rewrites dropped repeated query params from the original request.
    • Example: ?a=1&a=2&b=3 proxied upstream as ?a=1&b=3

Changes

  • Add a shared destination-substitution helper for redirect/rewrite params
  • Replace all destination param occurrences, including repeated params
  • Use the same substitution path in the locale-static redirect fast path
  • Preserve repeated original query params when proxying external rewrites
  • Keep destination query params authoritative when the destination already defines a key

Tests

Added unit regressions in tests/shims.test.ts for:

  • repeated rewrite param substitution
  • repeated redirect param substitution
  • repeated locale param substitution in locale-static redirects
  • repeated query param preservation in proxyExternalRequest()
  • destination query precedence during external proxy merges

Added integration coverage for:

  • App Router repeated redirect/rewrite param substitution
  • Pages Router dev repeated redirect/rewrite param substitution
  • Pages Router prod repeated redirect/rewrite param substitution
  • App Router external proxy preservation of repeated query params

Verification

pnpm test tests/shims.test.ts -t "proxyExternalRequest|matchRewrite with external URLs|matchRedirect destination param substitution"
pnpm test tests/app-router.test.ts -t "repeated dynamic params|external rewrite proxy credential stripping"
pnpm test tests/pages-router.test.ts -t "repeated dynamic params"
pnpm run fmt:check packages/vinext/src/config/config-matchers.ts tests/shims.test.ts tests/fixtures/app-basic/next.config.ts tests/fixtures/pages-basic/next.config.mjs tests/app-router.test.ts tests/pages-router.test.ts

🔄 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/422 **Author:** [@JaredStowell](https://github.com/JaredStowell) **Created:** 3/10/2026 **Status:** ✅ Merged **Merged:** 3/10/2026 **Merged by:** [@james-elicx](https://github.com/james-elicx) **Base:** `main` ← **Head:** `jstowell/fix-config-matchers-repeated-params` --- ### 📝 Commits (3) - [`b79ed65`](https://github.com/cloudflare/vinext/commit/b79ed65a16cc87199e04dc97ae8d08e92399fbe7) Update redirect matcher replacements - [`2cbbfc3`](https://github.com/cloudflare/vinext/commit/2cbbfc34fbb14806b50317144c6c626aaf9ab479) Fix rewrite param substitution - [`8d7b306`](https://github.com/cloudflare/vinext/commit/8d7b306952b867bb027f9735a9dc934641a8dbb2) fix nits ### 📊 Changes **7 files changed** (+248 additions, -23 deletions) <details> <summary>View changed files</summary> 📝 `packages/vinext/src/config/config-matchers.ts` (+49 -22) 📝 `tests/__snapshots__/entry-templates.test.ts.snap` (+1 -1) 📝 `tests/app-router.test.ts` (+32 -0) 📝 `tests/fixtures/app-basic/next.config.ts` (+11 -0) 📝 `tests/fixtures/pages-basic/next.config.mjs` (+9 -0) 📝 `tests/pages-router.test.ts` (+26 -0) 📝 `tests/shims.test.ts` (+120 -0) </details> ### 📄 Description Fix two `next.config` matcher bugs in `config-matchers.ts`: 1. Redirects and rewrites only replaced the first occurrence of a route param in the destination. - Example: `/post/:id -> /api/:id/:id` produced `/api/123/:id` 2. External rewrites dropped repeated query params from the original request. - Example: `?a=1&a=2&b=3` proxied upstream as `?a=1&b=3` ## Changes - Add a shared destination-substitution helper for redirect/rewrite params - Replace all destination param occurrences, including repeated params - Use the same substitution path in the locale-static redirect fast path - Preserve repeated original query params when proxying external rewrites - Keep destination query params authoritative when the destination already defines a key ## Tests Added unit regressions in `tests/shims.test.ts` for: - repeated rewrite param substitution - repeated redirect param substitution - repeated locale param substitution in locale-static redirects - repeated query param preservation in `proxyExternalRequest()` - destination query precedence during external proxy merges Added integration coverage for: - App Router repeated redirect/rewrite param substitution - Pages Router dev repeated redirect/rewrite param substitution - Pages Router prod repeated redirect/rewrite param substitution - App Router external proxy preservation of repeated query params ## Verification ```bash pnpm test tests/shims.test.ts -t "proxyExternalRequest|matchRewrite with external URLs|matchRedirect destination param substitution" pnpm test tests/app-router.test.ts -t "repeated dynamic params|external rewrite proxy credential stripping" pnpm test tests/pages-router.test.ts -t "repeated dynamic params" pnpm run fmt:check packages/vinext/src/config/config-matchers.ts tests/shims.test.ts tests/fixtures/app-basic/next.config.ts tests/fixtures/pages-basic/next.config.mjs tests/app-router.test.ts tests/pages-router.test.ts ``` --- <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:46 +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#560
No description provided.