Two parity gaps with Next.js were causing edge runtime API routes to fail
with 500 errors:
1. Edge API handlers received a plain `Request` object, so accessing
`req.nextUrl.searchParams` (the idiomatic pattern in Next.js edge API
routes) threw at runtime. Next.js wraps the request in `NextRequest`
before invoking the handler (NextRequestHint in
next/src/server/web/adapter.ts).
2. Only `export const config = { runtime: 'edge' }` was recognised as an
edge runtime declaration. Next.js also accepts a bare
`export const runtime = 'edge'` and resolves the effective runtime as
`config.runtime ?? config.config?.runtime`
(next/src/build/analysis/get-page-static-info.ts).
Both fixes are applied in dev (`server/api-handler.ts`) and prod
(`server/pages-api-route.ts`) so the two paths stay in parity.
Refs #1338
* fix(pages-api): execute edge API routes with Fetch Request
Pages API routes with config.runtime set to edge were still executed through the Node-style req/res adapter. That gives user handlers a plain headers object and turns valid Edge API code that returns a Response into a 500.
Detect edge and experimental-edge API route modules before Node body parsing, pass the Fetch Request through, and forward the returned Response. The dev Node bridge mirrors the generated Web Request path and preserves Set-Cookie response headers.
Regression coverage ports the relevant Next.js edge-async-local-storage contract for Fetch Request execution, concurrent AsyncLocalStorage isolation, and the dev bridge.
* fix(pages-api): stream edge API responses in dev
* fix(pages-api): handle closed dev edge streams
* fix(pages-api): stream dev edge request bodies
* fix(pages-api): validate dev edge forwarded protocol
* refactor: extract pages api route runtime
* refactor: share Pages ISR cache runtime (#684)
* fix: address Pages API route review feedback
- Replace fragile error.message string matches with typed PagesBodyParseError
(statusCode: 413) thrown from pages-node-compat.ts and api-handler.ts; the
existing instanceof catch in handlePagesApiRoute handles both 400 and 413
- Fix res.setHeader('set-cookie') to replace instead of append on repeated
calls, matching Node.js ServerResponse semantics
- Extract shared getMediaType/isJsonMediaType helpers and the body-parse error
class into pages-media-type.ts to eliminate drift between api-handler.ts and
pages-node-compat.ts
- Add unit tests for 404 (null match), missing default export (500), redirect
(1-arg and 2-arg), writeHead header lowercasing/array joining, setHeader/
getHeader round-trip, and set-cookie replace-not-append parity
---------
Co-authored-by: James <james@eli.cx>