* fix(middleware): clear nextUrl.basePath for absolute paths outside basePath (part of #1830)
* fix(middleware): reconcile NextURL basePath tests and App Router regression
Address two blocking issues from ask-bonk review on #1872:
1. Update 10 unit tests in tests/shims.test.ts that used basePath-stripped
URLs (e.g. http://localhost/dashboard with basePath="/app") — these tests
encoded the old incorrect behavior where basePath was always set from
config regardless of the URL. Switch them to prefixed input URLs
(http://localhost/app/dashboard) to match the new correct semantics.
2. Fix App Router regression: createNextRequest in middleware-runtime.ts was
receiving normalizedPathname already stripped of basePath (App Router
passes cleanPathname), so the NextRequest URL had no basePath prefix and
_stripBasePath incorrectly cleared basePath to "". Fix by applying
addBasePathToPathname before constructing the URL, mirroring the
un-stripped URL that Next.js's adapter always passes to middleware.
Also use addBasePathToPathname helper in prod-server.ts and deploy.ts
closures instead of duplicating the root-path edge-case logic.
* test(middleware): fix stale test assertions broken by basePath wrapper change
Update 9 tests in deploy.test.ts that checked for the old simple runMiddleware
passthrough ('runMiddleware: typeof runMiddleware === "function" ? runMiddleware : null')
which no longer matches the generated code after the basePath re-add wrapper was
introduced in the deploy adapter.
Fix 1 test in app-route-handler-runtime.test.ts that incorrectly expected NextURL
to re-add the basePath prefix to a URL that was already stripped of it. Per
getNextPathnameInfo semantics (the fix this PR implements for #1830), basePath is
only set when the pathname actually starts with the configured prefix — a stripped
URL stays stripped.
* fix(middleware): gate basePath re-add on in-basePath state and restore route handler URL parity
- Fix the missed import assertion in tests/deploy.test.ts (the generated
entry now imports addBasePathToPathname alongside hasBasePath/stripBasePath).
- Gate the basePath re-add in createNextRequest on a new hadBasePath option:
the unconditional re-add regressed the Pages out-of-basePath flow by
re-prefixing absolute-path requests the adapters deliberately left bare,
making middleware see nextUrl.basePath === "/root" instead of "". The
flag defaults to URL-derived (correct for prod/deploy Pages adapters) and
is asserted true by callers that pass pre-stripped URLs (App Router,
dev server).
- Re-add basePath in createTrackedAppRouteRequest so App Route handlers see
the original prefixed request.url / nextUrl.href and an active
nextUrl.basePath, matching Next.js (the routing layer strips basePath
before handlers run).
- Re-derive the active basePath from the configured value in
NextURL._stripBasePath on every parse, so href reassignment toggles
basePath like Next.js NextURL.analyze().
- Add unit tests covering the App Router nextUrl.basePath re-add, the Pages
in-/out-of-basePath flows, matcher evaluation against stripped paths, and
href re-derivation.
* refactor(middleware): extract shared wrapMiddlewareWithBasePath helper
The runMiddleware basePath re-add closure was duplicated verbatim in
prod-server.ts and the generated worker entry in deploy.ts. Extract it
to wrapMiddlewareWithBasePath in server/pages-request-pipeline.ts (both
adapters already import from that module) to keep the two adapters in
sync.
* test(middleware): add unit coverage for wrapMiddlewareWithBasePath
Covers the helper's gating contract directly: pass-through when
hadBasePath is false or basePath is empty, prefix re-add (preserving
query, headers, ctx, and opts), and idempotent re-add for an
already-prefixed URL.