nitro icon indicating copy to clipboard operation
nitro copied to clipboard

fix(vercel): handle isr requests with `passQuery: true`

Open pi0 opened this issue 4 months ago โ€ข 2 comments

Resolves #1880, #3594, #3651

Normally, with ISR matched routes, there is an (undocumented/legacy) x-now-route-matches header that contains the full pathname of the matched route. And Nitro vercel entry uses this header value to restore the original URL, but when passQuery isr route rule config is set, this header won't exist anymore, and the path is invalid (isr function name). We cannot always assume url query param is for ISR functions (it can be an actual query in normal routes!)

This PR changes the internal url query param to __isr_route and, if it exists, also attempts to rewrite without relying on legacy header but instead using a runtime protection check to make sure the requested route matches ISR route patterns.

We also make sure internal "__isr_route" is added to passQuery (if specified)


Beta testing:

package.json:

 "resolutions": {
    "nitropack": "https://pkg.pr.new/nitrojs/nitro/nitropack@3539"
  },

pi0 avatar Aug 19 '25 19:08 pi0

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
nitro.build Ready Ready Preview Comment Dec 9, 2025 8:50pm

vercel[bot] avatar Aug 19 '25 19:08 vercel[bot]

Open in StackBlitz

npm i https://pkg.pr.new/nitrojs/nitro/nitropack@3539

commit: 7753975

pkg-pr-new[bot] avatar Oct 13 '25 19:10 pkg-pr-new[bot]

hey @pi0, do you plan to release the fix in upcoming version maybe?

mkucmus avatar Nov 12 '25 12:11 mkucmus

Would love to see this merged. Using

  "resolutions": {
    "nitropack": "https://pkg.pr.new/nitrojs/nitro/nitropack@3539"
  }

works but is not ideal.

fmoessle avatar Nov 16 '25 14:11 fmoessle

The problem I face with https://pkg.pr.new/nitrojs/nitro/nitropack@3539: Building and starting the application with node-presets causes an issue with the public folder resolution in .output

Reproduction: https://github.com/fmoessle/nitro-vercel-isr/tree/test-3539-fix

pnpm build
pnpm preview

results in errors like this:

request error] [unhandled] [GET] http://[::]:3000/favicon.ico
 H3Error: ENOENT: no such file or directory, open 'XXX/florian/projects/test/nitro-vercel-isr/.output/server/chunks/public/favicon.ico'
    at async open (node:internal/fs/promises:634:25)
    ... 2 lines matching cause stack trace ...
    at async Server.toNodeHandle (file:///XXX/.output/server/chunks/nitro/nitro.mjs:1917:7) {
  cause: Error: ENOENT: no such file or directory, open 'XXX/.output/server/chunks/public/favicon.ico'
      at async open (node:internal/fs/promises:634:25)
      at async Object.readFile (node:internal/fs/promises:1238:14)
      at async Object.handler (file:///XXX/.output/server/chunks/nitro/nitro.mjs:1646:19)
      at async Server.toNodeHandle (file:///XXX/.output/server/chunks/nitro/nitro.mjs:1917:7) {
    errno: -2,
    code: 'ENOENT',
    syscall: 'open',
    path: 'XXX/.output/server/chunks/public/favicon.ico'
  },
  statusCode: 500,
  fatal: false,
  unhandled: true,
  statusMessage: undefined,
  data: undefined
}

There is no public folder in .output/server/chunks

fmoessle avatar Nov 16 '25 15:11 fmoessle

๐Ÿ“ Walkthrough

Walkthrough

The PR introduces a new constant ISR_URL_PARAM with value "__isr_route" to standardize Incremental Static Regeneration parameter handling across the Vercel preset. The constant replaces hardcoded parameter references in route matching, URL query handling, and test fixtures for consistent ISR routing behavior.

Changes

Cohort / File(s) Summary
New constant definition
src/presets/vercel/runtime/consts.ts
Introduces ISR_URL_PARAM constant with value "__isr_route" for centralized ISR parameter naming.
Runtime ISR flow updates
src/presets/vercel/runtime/vercel.ts
Refactors ISR detection and routing logic to extract ISR_URL_PARAM from headers or query parameters; adds route rules lookup via getRouteRulesForPath() and implements withQuery() for preserving non-ISR query parameters.
Utility and configuration
src/presets/vercel/utils.ts
Replaces hardcoded "url" parameter with ISR_URL_PARAM constant in route regex captures, query destinations, and prerender configuration allowlist.
Test updates
test/presets/vercel.test.ts
Updates ISR route assertions to use __isr_route in destination query strings and source regex named capture groups; adds "__isr_route" to prerender config allowQuery array.

Estimated code review effort

๐ŸŽฏ 3 (Moderate) | โฑ๏ธ ~20 minutes

  • src/presets/vercel/runtime/vercel.ts: Carefully verify the two-path ISR detection flow (header-based vs. passQuery-based) correctly handles URL parameter extraction and route rule resolution.
  • src/presets/vercel/utils.ts: Confirm all hardcoded "url" parameter references have been consistently replaced with ISR_URL_PARAM across regex patterns and prerender config generation.
  • Cross-file consistency: Ensure the constant definition, usage in runtime logic, utility transformations, and test expectations are properly aligned throughout the preset.

Pre-merge checks and finishing touches

โœ… Passed checks (5 passed)
Check name Status Explanation
Description check โœ… Passed The description is well-structured, relates to the changeset, references multiple linked issues, explains the problem and solution clearly.
Linked Issues check โœ… Passed The PR addresses issue #1880 (and others) by introducing __isr_route parameter to handle ISR requests with passQuery, ensuring query parameters are preserved in Vercel's caching behavior.
Out of Scope Changes check โœ… Passed All changes are directly scoped to fixing ISR request handling with passQuery support; changes to consts, runtime, utils, and tests are cohesively focused on this objective.
Docstring Coverage โœ… Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Title check โœ… Passed The title follows conventional commits format with type 'fix', scope 'vercel', and subject describing the change.
โœจ Finishing touches
  • [ ] ๐Ÿ“ Generate docstrings
๐Ÿงช Generate unit tests (beta)
  • [ ] Create PR with unit tests
  • [ ] Post copyable unit tests in a comment
  • [ ] Commit unit tests in branch fix/vercel-isr-url

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

โค๏ธ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

coderabbitai[bot] avatar Dec 09 '25 20:12 coderabbitai[bot]

@coderabbitai review

pi0 avatar Dec 09 '25 20:12 pi0

โœ… Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

coderabbitai[bot] avatar Dec 09 '25 20:12 coderabbitai[bot]

@fmoessle I couldn't reproduce error on your branch... This PR is also only affecting vercel preset not sure how can it break node-server. If you continue to having them on nightly or next release please feel free to raise an issue with more steps for reproduction.

pi0 avatar Dec 09 '25 21:12 pi0