vinext 1.2.1 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -9
- package/dist/_virtual/_rolldown/runtime.js +1 -1
- package/dist/build/action-owner-manifest.d.ts +3 -2
- package/dist/build/action-owner-manifest.js +18 -2
- package/dist/build/app-page-static-eligibility.d.ts +17 -1
- package/dist/build/app-page-static-eligibility.js +80 -13
- package/dist/build/clean-output.d.ts +2 -1
- package/dist/build/client-build-config.d.ts +77 -6
- package/dist/build/client-build-config.js +176 -12
- package/dist/build/client-reference-async.d.ts +48 -0
- package/dist/build/client-reference-async.js +123 -0
- package/dist/build/client-reference-chunks.d.ts +32 -0
- package/dist/build/client-reference-chunks.js +111 -0
- package/dist/build/client-reference-groups.d.ts +171 -0
- package/dist/build/client-reference-groups.js +572 -0
- package/dist/build/css-url-assets.d.ts +2 -1
- package/dist/build/google-fonts/fallback-metrics.d.ts +2 -1
- package/dist/build/google-fonts/find-font-files-in-css.d.ts +1 -0
- package/dist/build/google-fonts/find-font-files-in-css.js +17 -4
- package/dist/build/google-fonts/font-metadata.d.ts +2 -1
- package/dist/build/google-fonts/validate.d.ts +2 -1
- package/dist/build/inline-css.d.ts +2 -1
- package/dist/build/layout-classification.d.ts +2 -1
- package/dist/build/module-dependency-cache.d.ts +33 -1
- package/dist/build/module-dependency-cache.js +51 -1
- package/dist/build/next-client-runtime-manifests.d.ts +12 -2
- package/dist/build/next-client-runtime-manifests.js +19 -4
- package/dist/build/nitro-public-files.d.ts +24 -0
- package/dist/build/nitro-public-files.js +60 -0
- package/dist/build/pages-client-assets-module.js +1 -1
- package/dist/build/precompress.d.ts +2 -1
- package/dist/build/precompress.js +1 -1
- package/dist/build/prerender-paths.d.ts +2 -1
- package/dist/build/prerender-paths.js +5 -2
- package/dist/build/prerender-phase.d.ts +2 -1
- package/dist/build/prerender-server-pool.js +1 -1
- package/dist/build/prerender.d.ts +3 -2
- package/dist/build/prerender.js +5 -4
- package/dist/build/report.d.ts +2 -1
- package/dist/build/route-classification-injector.d.ts +2 -1
- package/dist/build/route-classification-manifest.d.ts +2 -1
- package/dist/build/run-prerender.d.ts +2 -1
- package/dist/build/server-actions-encryption-key.d.ts +24 -0
- package/dist/build/server-actions-encryption-key.js +101 -0
- package/dist/build/ssr-manifest.d.ts +3 -0
- package/dist/build/ssr-manifest.js +34 -2
- package/dist/build/standalone.d.ts +2 -1
- package/dist/cache/cache-adapters-virtual.d.ts +2 -1
- package/dist/cache.js +1 -2
- package/dist/check.d.ts +2 -1
- package/dist/check.js +4 -0
- package/dist/cli-args.d.ts +2 -1
- package/dist/cli.js +2 -0
- package/dist/client/client-redirect-matcher.js +2 -1
- package/dist/client/client-redirects.d.ts +4 -3
- package/dist/client/client-redirects.js +2 -1
- package/dist/client/client-rewrite-params.d.ts +9 -0
- package/dist/client/client-rewrite-params.js +20 -0
- package/dist/client/client-rewrites.d.ts +2 -1
- package/dist/client/dev-error-overlay-store.d.ts +2 -1
- package/dist/client/dev-error-overlay.js +2 -1
- package/dist/client/index.js +1 -2
- package/dist/client/instrumentation-client-state.js +5 -5
- package/dist/client/navigation-runtime.d.ts +28 -3
- package/dist/client/navigation-runtime.js +42 -11
- package/dist/client/pages-router-link-navigation.d.ts +2 -1
- package/dist/client/vinext-next-data.d.ts +25 -2
- package/dist/client/window-next.d.ts +2 -1
- package/dist/config/config-matchers.d.ts +27 -41
- package/dist/config/config-matchers.js +293 -270
- package/dist/config/config-source.d.ts +34 -0
- package/dist/config/config-source.js +141 -0
- package/dist/config/dotenv.d.ts +2 -1
- package/dist/config/header-params.d.ts +29 -0
- package/dist/config/header-params.js +106 -0
- package/dist/config/next-config.d.ts +20 -6
- package/dist/config/next-config.js +149 -11
- package/dist/config/tsconfig-paths.d.ts +2 -1
- package/dist/deps/.pnpm/image-size@2.0.4/deps/image-size/dist/esm/detector.js +23 -0
- package/dist/deps/.pnpm/image-size@2.0.4/deps/image-size/dist/esm/index.js +2 -0
- package/dist/deps/.pnpm/image-size@2.0.4/deps/image-size/dist/esm/lookup.js +25 -0
- package/dist/deps/.pnpm/image-size@2.0.4/deps/image-size/dist/esm/types/bmp.js +11 -0
- package/dist/deps/.pnpm/image-size@2.0.4/deps/image-size/dist/esm/types/cur.js +15 -0
- package/dist/deps/.pnpm/image-size@2.0.4/deps/image-size/dist/esm/types/dds.js +11 -0
- package/dist/deps/.pnpm/image-size@2.0.4/deps/image-size/dist/esm/types/gif.js +12 -0
- package/dist/deps/.pnpm/image-size@2.0.4/deps/image-size/dist/esm/types/heif.js +55 -0
- package/dist/deps/.pnpm/image-size@2.0.4/deps/image-size/dist/esm/types/icns.js +76 -0
- package/dist/deps/.pnpm/image-size@2.0.4/deps/image-size/dist/esm/types/ico.js +39 -0
- package/dist/deps/.pnpm/image-size@2.0.4/deps/image-size/dist/esm/types/index.js +46 -0
- package/dist/deps/.pnpm/image-size@2.0.4/deps/image-size/dist/esm/types/j2c.js +11 -0
- package/dist/deps/.pnpm/image-size@2.0.4/deps/image-size/dist/esm/types/jp2.js +21 -0
- package/dist/deps/.pnpm/image-size@2.0.4/deps/image-size/dist/esm/types/jpg.js +71 -0
- package/dist/deps/.pnpm/image-size@2.0.4/deps/image-size/dist/esm/types/jxl-stream.js +42 -0
- package/dist/deps/.pnpm/image-size@2.0.4/deps/image-size/dist/esm/types/jxl.js +46 -0
- package/dist/deps/.pnpm/image-size@2.0.4/deps/image-size/dist/esm/types/ktx.js +19 -0
- package/dist/deps/.pnpm/image-size@2.0.4/deps/image-size/dist/esm/types/png.js +28 -0
- package/dist/deps/.pnpm/image-size@2.0.4/deps/image-size/dist/esm/types/pnm.js +54 -0
- package/dist/deps/.pnpm/image-size@2.0.4/deps/image-size/dist/esm/types/psd.js +11 -0
- package/dist/deps/.pnpm/image-size@2.0.4/deps/image-size/dist/esm/types/svg.js +79 -0
- package/dist/deps/.pnpm/image-size@2.0.4/deps/image-size/dist/esm/types/tga.js +15 -0
- package/dist/deps/.pnpm/image-size@2.0.4/deps/image-size/dist/esm/types/tiff.js +96 -0
- package/dist/deps/.pnpm/image-size@2.0.4/deps/image-size/dist/esm/types/utils.js +53 -0
- package/dist/deps/.pnpm/image-size@2.0.4/deps/image-size/dist/esm/types/webp.js +45 -0
- package/dist/deps/.pnpm/image-size@2.0.4/deps/image-size/dist/esm/utils/bit-reader.js +38 -0
- package/dist/deps/.pnpm/ua-parser-js@1.0.35/deps/ua-parser-js/src/ua-parser.js +2 -2
- package/dist/entries/app-browser-entry.d.ts +34 -6
- package/dist/entries/app-browser-entry.js +103 -40
- package/dist/entries/app-rsc-entry.d.ts +4 -1
- package/dist/entries/app-rsc-entry.js +131 -66
- package/dist/entries/app-rsc-manifest.d.ts +12 -1
- package/dist/entries/app-rsc-manifest.js +73 -1
- package/dist/entries/app-ssr-entry.d.ts +4 -1
- package/dist/entries/app-ssr-entry.js +9 -2
- package/dist/entries/pages-client-entry.d.ts +1 -0
- package/dist/entries/pages-client-entry.js +6 -6
- package/dist/entries/pages-entry-helpers.js +1 -2
- package/dist/entries/pages-server-entry.d.ts +2 -1
- package/dist/entries/pages-server-entry.js +18 -15
- package/dist/entries/runtime-entry-module.d.ts +1 -0
- package/dist/entries/runtime-entry-module.js +4 -1
- package/dist/image/image-adapters-virtual.d.ts +2 -1
- package/dist/index.d.ts +11 -0
- package/dist/index.js +340 -116
- package/dist/init.js +17 -0
- package/dist/plugins/client-compile-hints.d.ts +30 -0
- package/dist/plugins/client-compile-hints.js +88 -0
- package/dist/plugins/client-reference-dedup.d.ts +2 -1
- package/dist/plugins/cloudflare-dev-module-urls.d.ts +2 -1
- package/dist/plugins/dynamic-preload-metadata.d.ts +3 -1
- package/dist/plugins/dynamic-preload-metadata.js +1 -1
- package/dist/plugins/environment.d.ts +2 -1
- package/dist/plugins/fonts.js +9 -12
- package/dist/plugins/ignore-dynamic-requests.d.ts +2 -1
- package/dist/plugins/import-meta-url.d.ts +2 -1
- package/dist/plugins/og-assets.d.ts +2 -1
- package/dist/plugins/og-assets.js +2 -3
- package/dist/plugins/optimize-imports.d.ts +27 -3
- package/dist/plugins/optimize-imports.js +106 -20
- package/dist/plugins/pages-node-externals.d.ts +2 -1
- package/dist/plugins/remove-console.d.ts +2 -1
- package/dist/plugins/require-condition-resolution.d.ts +2 -1
- package/dist/plugins/rsc-client-reference-loaders.d.ts +53 -1
- package/dist/plugins/rsc-client-reference-loaders.js +447 -27
- package/dist/plugins/rsc-client-shim-excludes.js +2 -0
- package/dist/plugins/sass.d.ts +2 -1
- package/dist/plugins/strip-server-exports.d.ts +2 -1
- package/dist/plugins/styled-jsx.d.ts +2 -1
- package/dist/plugins/transform-result.d.ts +2 -1
- package/dist/plugins/typeof-window.d.ts +2 -1
- package/dist/plugins/use-cache-callable.d.ts +5 -0
- package/dist/plugins/use-cache-callable.js +30 -8
- package/dist/plugins/worker-image-imports.d.ts +1 -0
- package/dist/plugins/worker-image-imports.js +2 -2
- package/dist/plugins/worker-use-server.d.ts +2 -1
- package/dist/routing/app-route-graph.d.ts +41 -1
- package/dist/routing/app-route-graph.js +122 -50
- package/dist/routing/browser-route-manifest.d.ts +44 -0
- package/dist/routing/browser-route-manifest.js +195 -0
- package/dist/routing/hashed-route-patterns.d.ts +4 -0
- package/dist/routing/hashed-route-patterns.js +22 -0
- package/dist/routing/optimistic-route-trie.d.ts +28 -0
- package/dist/routing/optimistic-route-trie.js +102 -0
- package/dist/routing/route-matching.d.ts +2 -1
- package/dist/routing/route-pattern.d.ts +2 -1
- package/dist/routing/route-validation.d.ts +6 -1
- package/dist/routing/route-validation.js +26 -10
- package/dist/server/accept-encoding.d.ts +2 -1
- package/dist/server/app-action-forwarding.d.ts +10 -1
- package/dist/server/app-action-forwarding.js +15 -1
- package/dist/server/app-bfcache-identity.d.ts +2 -1
- package/dist/server/app-browser-action-result.d.ts +2 -1
- package/dist/server/app-browser-client-reuse-manifest.d.ts +2 -1
- package/dist/server/app-browser-entry.js +175 -64
- package/dist/server/app-browser-error.d.ts +5 -2
- package/dist/server/app-browser-error.js +7 -2
- package/dist/server/app-browser-history-controller.d.ts +2 -1
- package/dist/server/app-browser-hydration.d.ts +2 -1
- package/dist/server/app-browser-interception-context.d.ts +4 -3
- package/dist/server/app-browser-mpa-navigation.d.ts +1 -0
- package/dist/server/app-browser-mpa-navigation.js +6 -5
- package/dist/server/app-browser-navigation-controller.d.ts +17 -6
- package/dist/server/app-browser-navigation-controller.js +103 -36
- package/dist/server/app-browser-popstate.d.ts +2 -1
- package/dist/server/app-browser-rsc-redirect.d.ts +2 -1
- package/dist/server/app-browser-server-action-client.d.ts +2 -1
- package/dist/server/app-browser-state.d.ts +2 -2
- package/dist/server/app-browser-state.js +1 -1
- package/dist/server/app-browser-stream.d.ts +2 -1
- package/dist/server/app-browser-visible-commit.d.ts +6 -5
- package/dist/server/app-client-reference-manifest.d.ts +31 -0
- package/dist/server/app-client-reference-manifest.js +46 -0
- package/dist/server/app-client-reference-preloader.d.ts +45 -2
- package/dist/server/app-client-reference-preloader.js +48 -10
- package/dist/server/app-elements-wire.d.ts +2 -1
- package/dist/server/app-elements.d.ts +2 -0
- package/dist/server/app-elements.js +3 -1
- package/dist/server/app-fallback-renderer.d.ts +9 -2
- package/dist/server/app-fallback-renderer.js +6 -2
- package/dist/server/app-history-state.d.ts +2 -1
- package/dist/server/app-inline-css-client.d.ts +2 -1
- package/dist/server/app-layout-param-observation.d.ts +2 -1
- package/dist/server/app-metadata-tracing.d.ts +2 -1
- package/dist/server/app-middleware.d.ts +6 -0
- package/dist/server/app-middleware.js +8 -10
- package/dist/server/app-optimistic-routing.d.ts +26 -11
- package/dist/server/app-optimistic-routing.js +38 -96
- package/dist/server/app-page-boundary-render.d.ts +20 -2
- package/dist/server/app-page-boundary-render.js +229 -39
- package/dist/server/app-page-boundary.d.ts +34 -5
- package/dist/server/app-page-boundary.js +40 -7
- package/dist/server/app-page-cache-finalizer.d.ts +2 -1
- package/dist/server/app-page-cache-finalizer.js +1 -1
- package/dist/server/app-page-cache-render.d.ts +10 -2
- package/dist/server/app-page-cache-render.js +15 -2
- package/dist/server/app-page-cache.js +2 -2
- package/dist/server/app-page-dispatch.d.ts +34 -1
- package/dist/server/app-page-dispatch.js +165 -34
- package/dist/server/app-page-element-builder.d.ts +17 -1
- package/dist/server/app-page-element-builder.js +187 -66
- package/dist/server/app-page-execution.d.ts +28 -1
- package/dist/server/app-page-execution.js +114 -5
- package/dist/server/app-page-head.d.ts +95 -3
- package/dist/server/app-page-head.js +307 -152
- package/dist/server/app-page-http-access-fallback-metadata.d.ts +48 -2
- package/dist/server/app-page-http-access-fallback-metadata.js +76 -1
- package/dist/server/app-page-method.d.ts +2 -1
- package/dist/server/app-page-probe.d.ts +2 -1
- package/dist/server/app-page-render-identity.d.ts +2 -1
- package/dist/server/app-page-render.d.ts +7 -1
- package/dist/server/app-page-render.js +38 -11
- package/dist/server/app-page-request.d.ts +14 -1
- package/dist/server/app-page-request.js +1 -1
- package/dist/server/app-page-route-wiring.d.ts +52 -2
- package/dist/server/app-page-route-wiring.js +197 -47
- package/dist/server/app-page-rsc-render-status.d.ts +3 -1
- package/dist/server/app-page-rsc-render-status.js +1 -0
- package/dist/server/app-page-search-params-observation.d.ts +8 -6
- package/dist/server/app-page-search-params-observation.js +16 -11
- package/dist/server/app-page-segment-plan.d.ts +2 -1
- package/dist/server/app-page-stream.d.ts +38 -1
- package/dist/server/app-page-stream.js +24 -4
- package/dist/server/app-pages-bridge.d.ts +4 -2
- package/dist/server/app-pages-bridge.js +11 -7
- package/dist/server/app-ppr-fallback-shell-render.d.ts +2 -1
- package/dist/server/app-ppr-fallback-shell.d.ts +2 -1
- package/dist/server/app-prerender-endpoints.d.ts +2 -1
- package/dist/server/app-prerender-static-params.d.ts +2 -1
- package/dist/server/app-prerender-static-params.js +3 -2
- package/dist/server/app-render-dependency.d.ts +11 -1
- package/dist/server/app-render-dependency.js +65 -6
- package/dist/server/app-request-stage-independent-entry.d.ts +2 -1
- package/dist/server/app-request-stage-independent-entry.js +2 -2
- package/dist/server/app-response-stage-entry.d.ts +2 -1
- package/dist/server/app-response-stage-entry.js +3 -3
- package/dist/server/app-route-handler-cache.d.ts +2 -1
- package/dist/server/app-route-handler-dispatch.d.ts +2 -1
- package/dist/server/app-route-handler-dispatch.js +4 -2
- package/dist/server/app-route-handler-execution.d.ts +4 -1
- package/dist/server/app-route-handler-execution.js +9 -2
- package/dist/server/app-route-handler-middleware-context.d.ts +2 -1
- package/dist/server/app-route-handler-middleware-context.js +3 -3
- package/dist/server/app-route-handler-response.d.ts +4 -2
- package/dist/server/app-route-handler-response.js +2 -2
- package/dist/server/app-route-handler-runtime.d.ts +4 -1
- package/dist/server/app-route-handler-runtime.js +20 -3
- package/dist/server/app-route-module-loader.d.ts +18 -1
- package/dist/server/app-route-module-loader.js +15 -6
- package/dist/server/app-route-tree-prefetch.d.ts +2 -1
- package/dist/server/app-route-tree.d.ts +20 -0
- package/dist/server/app-route-tree.js +18 -0
- package/dist/server/app-router-entry.js +2 -2
- package/dist/server/app-rsc-combined-handler.js +8 -1
- package/dist/server/app-rsc-error-handler.d.ts +2 -1
- package/dist/server/app-rsc-errors.d.ts +9 -1
- package/dist/server/app-rsc-errors.js +9 -2
- package/dist/server/app-rsc-handler.d.ts +6 -2
- package/dist/server/app-rsc-handler.js +152 -140
- package/dist/server/app-rsc-response-finalizer.d.ts +7 -1
- package/dist/server/app-rsc-response-finalizer.js +4 -1
- package/dist/server/app-rsc-response-stage.js +3 -1
- package/dist/server/app-rsc-route-matching.d.ts +39 -1
- package/dist/server/app-rsc-route-matching.js +25 -1
- package/dist/server/app-segment-config.d.ts +2 -1
- package/dist/server/app-segment-config.js +1 -14
- package/dist/server/app-server-action-execution.d.ts +25 -7
- package/dist/server/app-server-action-execution.js +53 -59
- package/dist/server/app-ssr-entry.d.ts +12 -0
- package/dist/server/app-ssr-entry.js +104 -48
- package/dist/server/app-ssr-error-meta.d.ts +2 -1
- package/dist/server/app-ssr-search-params-gate.d.ts +2 -1
- package/dist/server/app-ssr-stream.d.ts +29 -10
- package/dist/server/app-ssr-stream.js +311 -67
- package/dist/server/app-static-generation.d.ts +2 -1
- package/dist/server/app-streamed-client-references.d.ts +39 -0
- package/dist/server/app-streamed-client-references.js +156 -0
- package/dist/server/app-visited-response-cache.d.ts +2 -1
- package/dist/server/app-worker-stages.d.ts +2 -1
- package/dist/server/artifact-compatibility.d.ts +2 -1
- package/dist/server/bfcache-identity.d.ts +2 -1
- package/dist/server/cache-headers.d.ts +2 -1
- package/dist/server/cacheability-request.d.ts +2 -1
- package/dist/server/client-reuse-manifest.d.ts +2 -1
- package/dist/server/config-headers.d.ts +2 -1
- package/dist/server/config-headers.js +12 -3
- package/dist/server/csp.d.ts +2 -1
- package/dist/server/default-global-not-found-module.d.ts +2 -1
- package/dist/server/default-http-access-fallback-modules.d.ts +33 -0
- package/dist/server/default-http-access-fallback-modules.js +31 -0
- package/dist/server/defer-until-stream-consumed.d.ts +34 -0
- package/dist/server/defer-until-stream-consumed.js +154 -21
- package/dist/server/dev-lockfile.d.ts +32 -2
- package/dist/server/dev-lockfile.js +46 -2
- package/dist/server/dev-module-runner.d.ts +2 -1
- package/dist/server/dev-server.js +10 -3
- package/dist/server/fetch-handler.js +1 -2
- package/dist/server/file-based-metadata.d.ts +2 -1
- package/dist/server/framework-tracer.d.ts +2 -1
- package/dist/server/html.d.ts +1 -0
- package/dist/server/html.js +19 -1
- package/dist/server/http-conditional.d.ts +2 -1
- package/dist/server/http-error-responses.d.ts +2 -1
- package/dist/server/implicit-tags.d.ts +2 -1
- package/dist/server/isolate-shared-promise.d.ts +10 -0
- package/dist/server/isolate-shared-promise.js +33 -0
- package/dist/server/isr-cache.js +3 -2
- package/dist/server/metadata-route-build-data.d.ts +2 -1
- package/dist/server/metadata-route-build-data.js +1 -1
- package/dist/server/metadata-route-response.d.ts +2 -1
- package/dist/server/metadata-route-response.js +1 -1
- package/dist/server/metadata-routes.d.ts +2 -1
- package/dist/server/middleware-matcher-pattern.d.ts +0 -1
- package/dist/server/middleware-matcher-pattern.js +11 -140
- package/dist/server/middleware-matcher.js +5 -6
- package/dist/server/middleware-response-headers.d.ts +31 -0
- package/dist/server/middleware-response-headers.js +57 -1
- package/dist/server/middleware-runtime.d.ts +2 -1
- package/dist/server/middleware-runtime.js +26 -13
- package/dist/server/navigation-planner.d.ts +2 -2
- package/dist/server/navigation-trace.d.ts +2 -1
- package/dist/server/next-error-digest.d.ts +2 -1
- package/dist/server/nitro-public-files-plugin.d.ts +39 -0
- package/dist/server/nitro-public-files-plugin.js +106 -0
- package/dist/server/nitro-public-files.d.ts +22 -0
- package/dist/server/nitro-public-files.js +39 -0
- package/dist/server/opentelemetry-api.d.ts +2 -1
- package/dist/server/operation-token.d.ts +2 -1
- package/dist/server/pages-api-route.d.ts +2 -1
- package/dist/server/pages-asset-tags.d.ts +7 -1
- package/dist/server/pages-asset-tags.js +9 -2
- package/dist/server/pages-body-parser-config.d.ts +2 -1
- package/dist/server/pages-client-assets.d.ts +8 -1
- package/dist/server/pages-data-route.d.ts +2 -1
- package/dist/server/pages-document-asset-props.d.ts +2 -1
- package/dist/server/pages-document-initial-props.d.ts +2 -1
- package/dist/server/pages-execution-tracing.d.ts +2 -1
- package/dist/server/pages-execution-tracing.js +1 -1
- package/dist/server/pages-get-initial-props.d.ts +2 -1
- package/dist/server/pages-i18n.d.ts +18 -0
- package/dist/server/pages-i18n.js +18 -2
- package/dist/server/pages-node-compat.d.ts +5 -3
- package/dist/server/pages-node-compat.js +35 -16
- package/dist/server/pages-page-data.d.ts +7 -1
- package/dist/server/pages-page-data.js +35 -12
- package/dist/server/pages-page-handler.d.ts +3 -2
- package/dist/server/pages-page-handler.js +16 -7
- package/dist/server/pages-page-method.d.ts +2 -1
- package/dist/server/pages-page-response.d.ts +2 -1
- package/dist/server/pages-preview.d.ts +2 -1
- package/dist/server/pages-readiness.d.ts +2 -1
- package/dist/server/pages-request-pipeline.d.ts +8 -2
- package/dist/server/pages-request-pipeline.js +35 -40
- package/dist/server/pages-request-stage-entry.d.ts +2 -1
- package/dist/server/pages-request-stage-entry.js +16 -6
- package/dist/server/pages-response-stage-entry.d.ts +2 -1
- package/dist/server/pages-response-stage-entry.js +1 -1
- package/dist/server/pages-revalidate.js +1 -0
- package/dist/server/pages-route-data-kind.d.ts +2 -1
- package/dist/server/pages-router-entry.js +1 -1
- package/dist/server/prerender-cache-life-header.d.ts +2 -1
- package/dist/server/prerender-route-params.d.ts +2 -1
- package/dist/server/prod-server.d.ts +2 -2
- package/dist/server/prod-server.js +80 -36
- package/dist/server/proxy-trust.d.ts +6 -0
- package/dist/server/proxy-trust.js +12 -6
- package/dist/server/request-log.d.ts +2 -1
- package/dist/server/request-pipeline.d.ts +5 -0
- package/dist/server/request-pipeline.js +12 -1
- package/dist/server/request-tracing.d.ts +2 -1
- package/dist/server/request-tracing.js +1 -1
- package/dist/server/response-start-tracing.js +7 -29
- package/dist/server/rsc-render-stream.d.ts +4 -0
- package/dist/server/rsc-render-stream.js +25 -0
- package/dist/server/seed-cache.d.ts +2 -1
- package/dist/server/seed-cache.js +1 -1
- package/dist/server/server-reference-loader.js +10 -1
- package/dist/server/static-file-cache.d.ts +2 -1
- package/dist/server/static-file-cache.js +16 -3
- package/dist/server/static-layout-client-reuse-proof.d.ts +2 -1
- package/dist/server/worker-revalidation-context.d.ts +2 -1
- package/dist/server/worker-stages.d.ts +2 -1
- package/dist/server/worker-utils.js +1 -1
- package/dist/shims/app.d.ts +2 -1
- package/dist/shims/cache-callable-runtime.d.ts +2 -1
- package/dist/shims/cache-handler.d.ts +8 -3
- package/dist/shims/cache-handler.js +32 -11
- package/dist/shims/cache-request-state.d.ts +40 -3
- package/dist/shims/cache-request-state.js +70 -5
- package/dist/shims/cache-runtime.js +47 -19
- package/dist/shims/cache.d.ts +2 -2
- package/dist/shims/cache.js +17 -8
- package/dist/shims/caught-not-found-boundaries.d.ts +15 -0
- package/dist/shims/caught-not-found-boundaries.js +48 -0
- package/dist/shims/cdn-purge-routes.d.ts +25 -0
- package/dist/shims/cdn-purge-routes.js +77 -0
- package/dist/shims/client-locale.js +2 -1
- package/dist/shims/client-page-root.d.ts +2 -1
- package/dist/shims/config.d.ts +2 -1
- package/dist/shims/default-forbidden.d.ts +4 -0
- package/dist/shims/default-forbidden.js +18 -0
- package/dist/shims/default-not-found.d.ts +0 -5
- package/dist/shims/default-not-found.js +5 -41
- package/dist/shims/default-unauthorized.d.ts +4 -0
- package/dist/shims/default-unauthorized.js +18 -0
- package/dist/shims/dynamic.js +17 -4
- package/dist/shims/error-boundary.d.ts +39 -3
- package/dist/shims/error-boundary.js +31 -16
- package/dist/shims/font-google.js +1 -2
- package/dist/shims/font-utils.d.ts +3 -2
- package/dist/shims/font-utils.js +5 -3
- package/dist/shims/form.js +9 -4
- package/dist/shims/http-access-error-fallback.d.ts +7 -0
- package/dist/shims/http-access-error-fallback.js +47 -0
- package/dist/shims/image-props.d.ts +93 -0
- package/dist/shims/image-props.js +323 -0
- package/dist/shims/image.d.ts +4 -39
- package/dist/shims/image.js +4 -319
- package/dist/shims/internal/app-prefetch-fetch-queue.d.ts +22 -2
- package/dist/shims/internal/app-prefetch-fetch-queue.js +71 -18
- package/dist/shims/internal/app-route-prefetch-policy.d.ts +14 -3
- package/dist/shims/internal/app-route-prefetch-policy.js +29 -4
- package/dist/shims/internal/cache-context-accessor.d.ts +2 -1
- package/dist/shims/internal/client-reference-loader.d.ts +7 -0
- package/dist/shims/internal/client-reference-loader.js +91 -0
- package/dist/shims/internal/cookie-serialize.d.ts +2 -1
- package/dist/shims/internal/cookies.js +1 -2
- package/dist/shims/internal/headers-state.d.ts +9 -0
- package/dist/shims/internal/headers-state.js +19 -2
- package/dist/shims/internal/hybrid-client-route-owner-direct.d.ts +6 -2
- package/dist/shims/internal/hybrid-client-route-owner-direct.js +31 -14
- package/dist/shims/internal/hybrid-client-route-owner.js +8 -8
- package/dist/shims/internal/interpolate-as.d.ts +2 -1
- package/dist/shims/internal/pages-data-target.d.ts +2 -1
- package/dist/shims/internal/pages-data-url.d.ts +2 -1
- package/dist/shims/internal/thenable-well-known-properties.d.ts +2 -1
- package/dist/shims/link.js +198 -53
- package/dist/shims/metadata.d.ts +32 -11
- package/dist/shims/metadata.js +88 -26
- package/dist/shims/navigation-errors.d.ts +2 -1
- package/dist/shims/navigation.d.ts +23 -3
- package/dist/shims/navigation.js +91 -25
- package/dist/shims/og.js +35 -10
- package/dist/shims/pages-router-runtime.d.ts +2 -1
- package/dist/shims/ppr-fallback-shell.d.ts +2 -1
- package/dist/shims/request-context.d.ts +13 -0
- package/dist/shims/router.js +33 -43
- package/dist/shims/server.d.ts +31 -4
- package/dist/shims/server.js +58 -10
- package/dist/shims/thenable-params.d.ts +6 -1
- package/dist/shims/thenable-params.js +11 -2
- package/dist/shims/unified-request-context.d.ts +5 -0
- package/dist/shims/unified-request-context.js +5 -3
- package/dist/typegen.d.ts +2 -1
- package/dist/utils/asset-prefix.d.ts +7 -0
- package/dist/utils/asset-prefix.js +10 -1
- package/dist/utils/client-build-manifest.d.ts +4 -1
- package/dist/utils/client-build-manifest.js +20 -6
- package/dist/utils/client-entry-manifest.d.ts +13 -0
- package/dist/utils/client-entry-manifest.js +20 -1
- package/dist/utils/client-reference-chunks.d.ts +45 -0
- package/dist/utils/client-reference-chunks.js +30 -0
- package/dist/utils/client-runtime-metadata.d.ts +10 -1
- package/dist/utils/client-runtime-metadata.js +53 -9
- package/dist/utils/compare.d.ts +9 -0
- package/dist/utils/compare.js +15 -1
- package/dist/utils/lazy-chunks.d.ts +18 -0
- package/dist/utils/lazy-chunks.js +27 -1
- package/dist/utils/manifest-paths.d.ts +14 -0
- package/dist/utils/manifest-paths.js +22 -1
- package/dist/utils/middleware-request-headers.d.ts +2 -1
- package/dist/utils/path-to-regexp.d.ts +21 -0
- package/dist/{server/middleware-path-to-regexp.js → utils/path-to-regexp.js} +14 -11
- package/dist/utils/plugin-react-version.d.ts +15 -0
- package/dist/utils/plugin-react-version.js +64 -0
- package/dist/utils/project.d.ts +2 -1
- package/dist/utils/project.js +9 -1
- package/dist/utils/public-routes.d.ts +2 -0
- package/dist/utils/public-routes.js +18 -7
- package/dist/utils/query.d.ts +2 -1
- package/dist/utils/sorted-array.d.ts +2 -1
- package/dist/utils/vite-cli-invocation.d.ts +2 -1
- package/package.json +5 -5
- package/dist/deps/.pnpm/image-size@2.0.2/deps/image-size/dist/index.js +0 -808
- package/dist/server/default-not-found-module.d.ts +0 -19
- package/dist/server/default-not-found-module.js +0 -18
- package/dist/server/middleware-path-to-regexp.d.ts +0 -13
- package/dist/server/rsc-stream-hints.d.ts +0 -21
- package/dist/server/rsc-stream-hints.js +0 -227
- package/dist/utils/regex-safety.d.ts +0 -17
- package/dist/utils/regex-safety.js +0 -789
|
@@ -1,60 +1,32 @@
|
|
|
1
1
|
import { PRERENDER_REVALIDATE_HEADER, PRERENDER_REVALIDATE_ONLY_GENERATED_HEADER, VINEXT_MW_CTX_HEADER, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER, VINEXT_REVALIDATE_HOST_HEADER } from "../utils/protocol-headers.js";
|
|
2
2
|
import { buildRequestHeadersFromMiddlewareResponse, getUnconsumedMiddlewareRequestHeaders } from "../utils/middleware-request-headers.js";
|
|
3
|
-
import {
|
|
3
|
+
import { compileConfigSource, configSourceError, execConfigSource, matchConfigPattern } from "./config-source.js";
|
|
4
4
|
import { normalizeHost, parseCookies, requestContextFromRequest } from "./request-context.js";
|
|
5
5
|
import { isExternalUrl } from "../utils/external-url.js";
|
|
6
6
|
import { attachRequestCfMetadata } from "../server/request-pipeline.js";
|
|
7
7
|
import { substituteDestinationParams, substituteRedirectDestinationQuery } from "./destination-params.js";
|
|
8
|
+
import { compileHeaderParamTemplate, isValidHeaderPair } from "./header-params.js";
|
|
8
9
|
//#region src/config/config-matchers.ts
|
|
9
10
|
/**
|
|
10
|
-
* Cache for compiled regex patterns in matchConfigPattern.
|
|
11
|
-
*
|
|
12
|
-
* Redirect/rewrite patterns are static — they come from next.config.js and
|
|
13
|
-
* never change at runtime. Without caching, every request that hits the regex
|
|
14
|
-
* branch re-runs the full tokeniser walk + isSafeRegex + new RegExp() for
|
|
15
|
-
* every rule in the array. On apps with many locale-prefixed rules (which all
|
|
16
|
-
* contain `(` and therefore enter the regex branch) this dominated profiling
|
|
17
|
-
* at ~2.4 seconds of CPU self-time.
|
|
18
|
-
*
|
|
19
|
-
* Value is `null` when safeRegExp rejected the pattern (ReDoS risk), so we
|
|
20
|
-
* skip it on subsequent requests too without re-running the scanner.
|
|
21
|
-
*/
|
|
22
|
-
const _compiledPatternCache = /* @__PURE__ */ new Map();
|
|
23
|
-
/**
|
|
24
|
-
* Cache for compiled header source regexes in matchHeaders.
|
|
25
|
-
*
|
|
26
|
-
* Each NextHeader rule has a `source` that is run through escapeHeaderSource()
|
|
27
|
-
* then safeRegExp() to produce a RegExp. Both are pure functions of the source
|
|
28
|
-
* string and the result never changes. Without caching, every request
|
|
29
|
-
* re-runs the full escapeHeaderSource tokeniser + isSafeRegex scan + new RegExp()
|
|
30
|
-
* for every header rule.
|
|
31
|
-
*
|
|
32
|
-
* Value is `null` when safeRegExp rejected the pattern (ReDoS risk).
|
|
33
|
-
*/
|
|
34
|
-
const _compiledHeaderSourceCache = /* @__PURE__ */ new Map();
|
|
35
|
-
/**
|
|
36
11
|
* Cache for compiled has/missing condition value regexes in checkSingleCondition.
|
|
37
12
|
*
|
|
38
|
-
* Each has/missing condition may carry a `value` string that is
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
13
|
+
* Each has/missing condition may carry a `value` string that is compiled as a
|
|
14
|
+
* regex for matching against header/cookie/query/host values. The condition
|
|
15
|
+
* objects are static (from next.config.js) so the compiled RegExp never
|
|
16
|
+
* changes. Without caching, the value is recompiled on every request for every
|
|
17
|
+
* condition on every rule.
|
|
43
18
|
*
|
|
44
|
-
* Value is `null` when
|
|
45
|
-
*
|
|
19
|
+
* Value is `null` when the value is not a valid regex (use exact string
|
|
20
|
+
* comparison instead).
|
|
46
21
|
*/
|
|
47
22
|
const _compiledConditionCache = /* @__PURE__ */ new Map();
|
|
48
23
|
/**
|
|
49
|
-
* Generic helper for the regex compilation
|
|
24
|
+
* Generic helper for the regex compilation cache above.
|
|
50
25
|
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
26
|
+
* The cache stores the compiled artifact (or `null` when the pattern could
|
|
27
|
+
* not be compiled) the first time a key is seen, and reuses it forever. The
|
|
53
28
|
* `undefined` sentinel distinguishes "not yet seen" from "seen and rejected"
|
|
54
|
-
* so we never
|
|
55
|
-
*
|
|
56
|
-
* Keep the security path intact: `compile()` is responsible for calling
|
|
57
|
-
* safeRegExp(); this helper only handles caching.
|
|
29
|
+
* so we never recompile the same input.
|
|
58
30
|
*/
|
|
59
31
|
function getCachedRegex(cache, key, compile) {
|
|
60
32
|
let value = cache.get(key);
|
|
@@ -106,8 +78,36 @@ function getCachedRegex(cache, key, compile) {
|
|
|
106
78
|
* by `applyLocaleToRoutes` for the locale-capture variant)
|
|
107
79
|
* Both forms benefit from O(1) suffix lookup; the optionality is recorded
|
|
108
80
|
* on the entry so we know whether to try the no-locale-prefix bucket.
|
|
81
|
+
*
|
|
82
|
+
* The index must match exactly what the compiled source would. So the param
|
|
83
|
+
* name follows path-to-regexp's `\w` name lexer, the alternatives are plain
|
|
84
|
+
* words, possibly empty (a `.*` alternative could span several segments), and
|
|
85
|
+
* the suffix class only admits characters path-to-regexp treats as literals:
|
|
86
|
+
* `:` (param), `*` and `+` (modifiers), `(`, `{`, `?` and `\` are excluded.
|
|
109
87
|
*/
|
|
110
|
-
const _LOCALE_STATIC_RE =
|
|
88
|
+
const _LOCALE_STATIC_RE = /^\/:\w+\(([\w-]*(?:\|[\w-]*)*)\)(\??)\/([a-zA-Z0-9_~.%@!$&',;=/-]+)$/;
|
|
89
|
+
/**
|
|
90
|
+
* ECMAScript's non-Unicode Canonicalize operation, which a RegExp with `i` and
|
|
91
|
+
* without `u` compares characters by: it keeps the original UTF-16 code unit
|
|
92
|
+
* when uppercasing expands it or maps a non-ASCII character to ASCII.
|
|
93
|
+
*/
|
|
94
|
+
function canonicalizeIgnoreCase(character) {
|
|
95
|
+
const upper = character.toUpperCase();
|
|
96
|
+
if (upper.length !== 1) return character;
|
|
97
|
+
if (character.charCodeAt(0) >= 128 && upper.charCodeAt(0) < 128) return character;
|
|
98
|
+
return upper;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Folds case as a RegExp with `i` and without `u` compares characters, as
|
|
102
|
+
* the compiled source does: `toLowerCase()` would also read the Kelvin sign
|
|
103
|
+
* as `k`.
|
|
104
|
+
*/
|
|
105
|
+
function foldCase(value) {
|
|
106
|
+
if (!/[^ -~]/.test(value)) return value.toUpperCase();
|
|
107
|
+
let folded = "";
|
|
108
|
+
for (let i = 0; i < value.length; i++) folded += canonicalizeIgnoreCase(value[i]);
|
|
109
|
+
return folded;
|
|
110
|
+
}
|
|
111
111
|
const _redirectIndexCache = /* @__PURE__ */ new WeakMap();
|
|
112
112
|
/**
|
|
113
113
|
* Build (or retrieve from cache) the redirect index for a given redirects array.
|
|
@@ -124,12 +124,12 @@ function _getRedirectIndex(redirects) {
|
|
|
124
124
|
for (let i = 0; i < redirects.length; i++) {
|
|
125
125
|
const redirect = redirects[i];
|
|
126
126
|
const m = _LOCALE_STATIC_RE.exec(redirect.source);
|
|
127
|
-
if (m) {
|
|
127
|
+
if (m && m[1] !== "" && !m[3].endsWith("/")) {
|
|
128
128
|
const paramName = redirect.source.slice(2, redirect.source.indexOf("("));
|
|
129
129
|
const alternation = m[1];
|
|
130
130
|
const optional = m[2] === "?";
|
|
131
131
|
const suffix = "/" + m[3];
|
|
132
|
-
const altRe =
|
|
132
|
+
const altRe = compileRegExp("^(?:" + alternation + ")$", "i");
|
|
133
133
|
if (!altRe) {
|
|
134
134
|
linear.push([i, redirect]);
|
|
135
135
|
continue;
|
|
@@ -141,7 +141,7 @@ function _getRedirectIndex(redirects) {
|
|
|
141
141
|
redirect,
|
|
142
142
|
originalIndex: i
|
|
143
143
|
};
|
|
144
|
-
const bucketKey = suffix
|
|
144
|
+
const bucketKey = foldCase(suffix);
|
|
145
145
|
const bucket = localeStatic.get(bucketKey);
|
|
146
146
|
if (bucket) bucket.push(entry);
|
|
147
147
|
else localeStatic.set(bucketKey, [entry]);
|
|
@@ -185,77 +185,18 @@ function stripHopByHopRequestHeaders(headers) {
|
|
|
185
185
|
for (const token of connectionTokens) headers.delete(token);
|
|
186
186
|
}
|
|
187
187
|
/**
|
|
188
|
-
*
|
|
189
|
-
*
|
|
190
|
-
* Uses the same deterministic structural analysis as middleware matcher
|
|
191
|
-
* validation. Nested bounded repetition is accepted only when its repeated
|
|
192
|
-
* language has fixed width and unambiguous branches; a fixed outer count can
|
|
193
|
-
* otherwise still cause polynomially catastrophic backtracking on long near
|
|
194
|
-
* misses.
|
|
195
|
-
*
|
|
196
|
-
* Returns true if the pattern appears safe, false if it's potentially dangerous.
|
|
197
|
-
*/
|
|
198
|
-
function isSafeRegex(pattern, flags) {
|
|
199
|
-
return analyzeRegexSafety(pattern, { ignoreCase: flags?.includes("i") }) === null;
|
|
200
|
-
}
|
|
201
|
-
/**
|
|
202
|
-
* Compile a regex pattern safely. Returns the compiled RegExp or null if the
|
|
203
|
-
* pattern is invalid or vulnerable to ReDoS.
|
|
188
|
+
* Compile a regex from next.config, or return null when it is invalid.
|
|
204
189
|
*
|
|
205
|
-
*
|
|
190
|
+
* Like Next.js, patterns are not checked for catastrophic backtracking: they
|
|
191
|
+
* run as written.
|
|
206
192
|
*/
|
|
207
|
-
function
|
|
208
|
-
if (!isSafeRegex(pattern, flags)) {
|
|
209
|
-
console.warn(`[vinext] Rejecting potentially unsafe regex pattern (ReDoS risk): ${pattern}\n Nested or ambiguous repetition can cause catastrophic backtracking.\n Simplify the pattern to make repeated matches fixed and unambiguous.`);
|
|
210
|
-
return null;
|
|
211
|
-
}
|
|
193
|
+
function compileRegExp(pattern, flags) {
|
|
212
194
|
try {
|
|
213
195
|
return new RegExp(pattern, flags);
|
|
214
196
|
} catch {
|
|
215
197
|
return null;
|
|
216
198
|
}
|
|
217
199
|
}
|
|
218
|
-
/**
|
|
219
|
-
* Convert a Next.js header/rewrite/redirect source pattern into a regex string.
|
|
220
|
-
*
|
|
221
|
-
* Regex groups in the source (e.g. `(\d+)`) are extracted first, the remaining
|
|
222
|
-
* text is escaped/converted in a **single pass** (avoiding chained `.replace()`
|
|
223
|
-
* which CodeQL flags as incomplete sanitization), then groups are restored.
|
|
224
|
-
*/
|
|
225
|
-
function escapeHeaderSource(source) {
|
|
226
|
-
const S = "";
|
|
227
|
-
const groups = [];
|
|
228
|
-
const withPlaceholders = source.replace(/\(([^)]+)\)/g, (_m, inner) => {
|
|
229
|
-
groups.push(inner);
|
|
230
|
-
return `${S}G${groups.length - 1}${S}`;
|
|
231
|
-
});
|
|
232
|
-
let result = "";
|
|
233
|
-
const re = new RegExp(`${S}G(\\d+)${S}|:[\\w-]+|[.+?*]|[^.+?*:\\uE000]+`, "g");
|
|
234
|
-
let m;
|
|
235
|
-
while ((m = re.exec(withPlaceholders)) !== null) if (m[1] !== void 0) result += `(${groups[Number(m[1])]})`;
|
|
236
|
-
else if (m[0].startsWith(":")) {
|
|
237
|
-
const constraintMatch = withPlaceholders.slice(re.lastIndex).match(new RegExp(`^${S}G(\\d+)${S}`));
|
|
238
|
-
if (constraintMatch) {
|
|
239
|
-
re.lastIndex += constraintMatch[0].length;
|
|
240
|
-
result += `(${groups[Number(constraintMatch[1])]})`;
|
|
241
|
-
} else result += "[^/]+";
|
|
242
|
-
} else switch (m[0]) {
|
|
243
|
-
case ".":
|
|
244
|
-
result += "\\.";
|
|
245
|
-
break;
|
|
246
|
-
case "+":
|
|
247
|
-
result += "\\+";
|
|
248
|
-
break;
|
|
249
|
-
case "?":
|
|
250
|
-
result += "\\?";
|
|
251
|
-
break;
|
|
252
|
-
case "*":
|
|
253
|
-
result += ".*";
|
|
254
|
-
break;
|
|
255
|
-
default: result += m[0];
|
|
256
|
-
}
|
|
257
|
-
return result;
|
|
258
|
-
}
|
|
259
200
|
const _BASEPATH_DEFAULT = {
|
|
260
201
|
basePath: "",
|
|
261
202
|
hadBasePath: true
|
|
@@ -360,11 +301,11 @@ function matchSingleCondition(condition, ctx) {
|
|
|
360
301
|
}
|
|
361
302
|
/**
|
|
362
303
|
* Return a cached RegExp for a has/missing condition value string, compiling
|
|
363
|
-
* on first use. Returns null if
|
|
364
|
-
*
|
|
304
|
+
* on first use. Returns null if the value is not a valid regex (fall back to
|
|
305
|
+
* exact string comparison).
|
|
365
306
|
*/
|
|
366
307
|
function _cachedConditionRegex(value) {
|
|
367
|
-
return getCachedRegex(_compiledConditionCache, value, () =>
|
|
308
|
+
return getCachedRegex(_compiledConditionCache, value, () => compileRegExp(`^${value}$`));
|
|
368
309
|
}
|
|
369
310
|
/**
|
|
370
311
|
* Check all has/missing conditions for a config rule.
|
|
@@ -389,125 +330,13 @@ function checkHasConditions(has, missing, ctx) {
|
|
|
389
330
|
return collectConditionParams(has, missing, ctx) !== null;
|
|
390
331
|
}
|
|
391
332
|
/**
|
|
392
|
-
*
|
|
393
|
-
*
|
|
394
|
-
*
|
|
395
|
-
*/
|
|
396
|
-
function extractConstraint(str, re) {
|
|
397
|
-
if (str[re.lastIndex] !== "(") return null;
|
|
398
|
-
const start = re.lastIndex + 1;
|
|
399
|
-
let depth = 1;
|
|
400
|
-
let i = start;
|
|
401
|
-
while (i < str.length && depth > 0) {
|
|
402
|
-
if (str[i] === "(") depth++;
|
|
403
|
-
else if (str[i] === ")") depth--;
|
|
404
|
-
i++;
|
|
405
|
-
}
|
|
406
|
-
if (depth !== 0) return null;
|
|
407
|
-
re.lastIndex = i;
|
|
408
|
-
return str.slice(start, i - 1);
|
|
409
|
-
}
|
|
410
|
-
/**
|
|
411
|
-
* Match a Next.js config pattern (from redirects/rewrites sources) against a pathname.
|
|
412
|
-
* Returns matched params or null.
|
|
413
|
-
*
|
|
414
|
-
* Supports:
|
|
415
|
-
* :param - matches a single path segment
|
|
416
|
-
* :param* - matches zero or more segments (catch-all)
|
|
417
|
-
* :param+ - matches one or more segments
|
|
418
|
-
* (regex) - inline regex patterns in the source
|
|
419
|
-
* :param(constraint) - named param with inline regex constraint
|
|
420
|
-
*/
|
|
421
|
-
/**
|
|
422
|
-
* Strip a single trailing slash from a pathname for config-source matching.
|
|
423
|
-
*
|
|
424
|
-
* Next.js conditionally appends `(/)?` to rewrite/redirect/header source
|
|
425
|
-
* regexes when `trailingSlash: true` (see Next.js
|
|
426
|
-
* `resolve-rewrites.ts` and `server-utils.ts:checkRewrite`). Rather than
|
|
427
|
-
* threading the trailingSlash flag through every matcher, we unconditionally
|
|
428
|
-
* strip a trailing slash from the incoming pathname. When `trailingSlash: false`
|
|
429
|
-
* the request pipeline emits a normalizing redirect (step 3) before config
|
|
430
|
-
* rewrites/redirects (step 6) ever run, so the pathname is already slash-free;
|
|
431
|
-
* the unconditional strip is defense-in-depth for that ordering. When
|
|
432
|
-
* `trailingSlash: true` it bridges the gap between the canonicalized request
|
|
433
|
-
* path (`/rewrite-1/`) and source patterns written without a trailing slash
|
|
434
|
-
* (`/rewrite-1`).
|
|
435
|
-
*
|
|
436
|
-
* The root path `"/"` is preserved as-is.
|
|
333
|
+
* Strip one trailing slash, preserving the root path `"/"`. Compiled sources
|
|
334
|
+
* accept an optional trailing slash, so the redirect index looks up the
|
|
335
|
+
* slash-free form.
|
|
437
336
|
*/
|
|
438
337
|
function stripTrailingSlashForConfigMatch(value) {
|
|
439
338
|
return value.length > 1 && value.endsWith("/") ? value.slice(0, -1) : value;
|
|
440
339
|
}
|
|
441
|
-
function configPathEquals(a, b) {
|
|
442
|
-
return a.toLowerCase() === b.toLowerCase();
|
|
443
|
-
}
|
|
444
|
-
function configPathStartsWith(pathname, prefix) {
|
|
445
|
-
return pathname.slice(0, prefix.length).toLowerCase() === prefix.toLowerCase();
|
|
446
|
-
}
|
|
447
|
-
function matchConfigPattern(pathname, pattern) {
|
|
448
|
-
const pathnameHadTrailingSlash = pathname.length > 1 && pathname.endsWith("/");
|
|
449
|
-
pathname = stripTrailingSlashForConfigMatch(pathname);
|
|
450
|
-
if (pathnameHadTrailingSlash) pattern = stripTrailingSlashForConfigMatch(pattern);
|
|
451
|
-
const catchAllAnchor = /:[\w-]+[*+]/.test(pattern);
|
|
452
|
-
const namedParamCount = (pattern.match(/:[\w-]+/g) || []).length;
|
|
453
|
-
if (pattern.includes("(") || pattern.includes("\\") || /:[\w-]+[*+][^/]/.test(pattern) || /:[\w-]+\./.test(pattern) || /[^/]:[\w-]+/.test(pattern) || catchAllAnchor && namedParamCount > 1) try {
|
|
454
|
-
const compiled = getCachedRegex(_compiledPatternCache, pattern, () => {
|
|
455
|
-
const paramNames = [];
|
|
456
|
-
let regexStr = "";
|
|
457
|
-
const tokenRe = /:([\w-]+)|[.]|[^:.]+/g;
|
|
458
|
-
let tok;
|
|
459
|
-
while ((tok = tokenRe.exec(pattern)) !== null) if (tok[1] !== void 0) {
|
|
460
|
-
const name = tok[1];
|
|
461
|
-
const rest = pattern.slice(tokenRe.lastIndex);
|
|
462
|
-
if (rest.startsWith("*") || rest.startsWith("+")) {
|
|
463
|
-
const quantifier = rest[0];
|
|
464
|
-
tokenRe.lastIndex += 1;
|
|
465
|
-
const constraint = extractConstraint(pattern, tokenRe);
|
|
466
|
-
paramNames.push(name);
|
|
467
|
-
if (constraint !== null) regexStr += `(${constraint})`;
|
|
468
|
-
else regexStr += quantifier === "*" ? "(.*)" : "(.+)";
|
|
469
|
-
} else {
|
|
470
|
-
const constraint = extractConstraint(pattern, tokenRe);
|
|
471
|
-
paramNames.push(name);
|
|
472
|
-
regexStr += constraint !== null ? `(${constraint})` : "([^/]+)";
|
|
473
|
-
}
|
|
474
|
-
} else if (tok[0] === ".") regexStr += "\\.";
|
|
475
|
-
else regexStr += tok[0];
|
|
476
|
-
const re = safeRegExp("^" + regexStr + "$", "i");
|
|
477
|
-
return re ? {
|
|
478
|
-
re,
|
|
479
|
-
paramNames
|
|
480
|
-
} : null;
|
|
481
|
-
});
|
|
482
|
-
if (!compiled) return null;
|
|
483
|
-
const match = compiled.re.exec(pathname);
|
|
484
|
-
if (!match) return null;
|
|
485
|
-
const params = Object.create(null);
|
|
486
|
-
for (let i = 0; i < compiled.paramNames.length; i++) params[compiled.paramNames[i]] = match[i + 1] ?? "";
|
|
487
|
-
return params;
|
|
488
|
-
} catch {}
|
|
489
|
-
const catchAllMatch = pattern.match(/:([\w-]+)(\*|\+)$/);
|
|
490
|
-
if (catchAllMatch) {
|
|
491
|
-
const prefix = pattern.slice(0, pattern.lastIndexOf(":"));
|
|
492
|
-
const paramName = catchAllMatch[1];
|
|
493
|
-
const isPlus = catchAllMatch[2] === "+";
|
|
494
|
-
const prefixNoSlash = prefix.replace(/\/$/, "");
|
|
495
|
-
if (!configPathStartsWith(pathname, prefixNoSlash)) return null;
|
|
496
|
-
const charAfter = pathname[prefixNoSlash.length];
|
|
497
|
-
if (charAfter !== void 0 && charAfter !== "/") return null;
|
|
498
|
-
const rest = pathname.slice(prefixNoSlash.length);
|
|
499
|
-
if (isPlus && (!rest || rest === "/")) return null;
|
|
500
|
-
let restValue = rest.startsWith("/") ? rest.slice(1) : rest;
|
|
501
|
-
return { [paramName]: restValue };
|
|
502
|
-
}
|
|
503
|
-
const parts = pattern.split("/");
|
|
504
|
-
const pathParts = pathname.split("/");
|
|
505
|
-
if (parts.length !== pathParts.length) return null;
|
|
506
|
-
const params = Object.create(null);
|
|
507
|
-
for (let i = 0; i < parts.length; i++) if (parts[i].startsWith(":")) params[parts[i].slice(1)] = pathParts[i];
|
|
508
|
-
else if (!configPathEquals(parts[i], pathParts[i])) return null;
|
|
509
|
-
return params;
|
|
510
|
-
}
|
|
511
340
|
/**
|
|
512
341
|
* Apply redirect rules from next.config.js.
|
|
513
342
|
* Returns the redirect info if a redirect was matched, or null.
|
|
@@ -550,7 +379,7 @@ function matchRedirect(pathname, redirects, ctx, basePathState = _BASEPATH_DEFAU
|
|
|
550
379
|
let localeMatch = null;
|
|
551
380
|
let localeMatchIndex = Infinity;
|
|
552
381
|
if (index.localeStatic.size > 0) {
|
|
553
|
-
const noLocaleBucket = index.localeStatic.get(normalizedPathname
|
|
382
|
+
const noLocaleBucket = index.localeStatic.get(foldCase(normalizedPathname));
|
|
554
383
|
if (noLocaleBucket) for (const entry of noLocaleBucket) {
|
|
555
384
|
if (!entry.optional) continue;
|
|
556
385
|
if (entry.originalIndex >= localeMatchIndex) continue;
|
|
@@ -559,10 +388,13 @@ function matchRedirect(pathname, redirects, ctx, basePathState = _BASEPATH_DEFAU
|
|
|
559
388
|
onRuleSourceMatch?.(redirect);
|
|
560
389
|
const conditionParams = redirect.has || redirect.missing ? collectConditionParams(redirect.has, redirect.missing, ctx) : _emptyParams();
|
|
561
390
|
if (!conditionParams) continue;
|
|
562
|
-
localeMatch =
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
391
|
+
localeMatch = {
|
|
392
|
+
redirect,
|
|
393
|
+
params: {
|
|
394
|
+
[entry.paramName]: "",
|
|
395
|
+
...conditionParams
|
|
396
|
+
}
|
|
397
|
+
};
|
|
566
398
|
localeMatchIndex = entry.originalIndex;
|
|
567
399
|
break;
|
|
568
400
|
}
|
|
@@ -570,7 +402,7 @@ function matchRedirect(pathname, redirects, ctx, basePathState = _BASEPATH_DEFAU
|
|
|
570
402
|
if (slashTwo !== -1) {
|
|
571
403
|
const suffix = normalizedPathname.slice(slashTwo);
|
|
572
404
|
const localePart = normalizedPathname.slice(1, slashTwo);
|
|
573
|
-
const localeBucket = index.localeStatic.get(suffix
|
|
405
|
+
const localeBucket = index.localeStatic.get(foldCase(suffix));
|
|
574
406
|
if (localeBucket) for (const entry of localeBucket) {
|
|
575
407
|
if (entry.originalIndex >= localeMatchIndex) continue;
|
|
576
408
|
if (!entry.altRe.test(localePart)) continue;
|
|
@@ -579,10 +411,13 @@ function matchRedirect(pathname, redirects, ctx, basePathState = _BASEPATH_DEFAU
|
|
|
579
411
|
onRuleSourceMatch?.(redirect);
|
|
580
412
|
const conditionParams = redirect.has || redirect.missing ? collectConditionParams(redirect.has, redirect.missing, ctx) : _emptyParams();
|
|
581
413
|
if (!conditionParams) continue;
|
|
582
|
-
localeMatch =
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
414
|
+
localeMatch = {
|
|
415
|
+
redirect,
|
|
416
|
+
params: {
|
|
417
|
+
[entry.paramName]: localePart,
|
|
418
|
+
...conditionParams
|
|
419
|
+
}
|
|
420
|
+
};
|
|
586
421
|
localeMatchIndex = entry.originalIndex;
|
|
587
422
|
break;
|
|
588
423
|
}
|
|
@@ -599,10 +434,10 @@ function matchRedirect(pathname, redirects, ctx, basePathState = _BASEPATH_DEFAU
|
|
|
599
434
|
return resolveRedirectMatch(redirect, {
|
|
600
435
|
...params,
|
|
601
436
|
...conditionParams
|
|
602
|
-
});
|
|
437
|
+
}, basePathState);
|
|
603
438
|
}
|
|
604
439
|
}
|
|
605
|
-
return localeMatch;
|
|
440
|
+
return localeMatch && resolveRedirectMatch(localeMatch.redirect, localeMatch.params, basePathState);
|
|
606
441
|
}
|
|
607
442
|
/**
|
|
608
443
|
* Apply rewrite rules from next.config.js.
|
|
@@ -615,17 +450,17 @@ function matchRedirect(pathname, redirects, ctx, basePathState = _BASEPATH_DEFAU
|
|
|
615
450
|
function matchRewrite(pathname, rewrites, ctx, basePathState = _BASEPATH_DEFAULT, paramsPathname = pathname, onRuleSourceMatch) {
|
|
616
451
|
for (const rewrite of rewrites) {
|
|
617
452
|
if (!shouldEvaluateRule(rewrite.basePath, basePathState)) continue;
|
|
618
|
-
const
|
|
619
|
-
if (
|
|
453
|
+
const matched = execConfigSource(pathname, rewrite.source);
|
|
454
|
+
if (matched) {
|
|
620
455
|
onRuleSourceMatch?.(rewrite);
|
|
621
|
-
const params = paramsPathname === pathname ?
|
|
456
|
+
const { params, unmatched } = paramsPathname === pathname ? matched : execConfigSource(paramsPathname, rewrite.source) ?? matched;
|
|
622
457
|
const conditionParams = rewrite.has || rewrite.missing ? collectConditionParams(rewrite.has, rewrite.missing, ctx) : _emptyParams();
|
|
623
458
|
if (!conditionParams) continue;
|
|
624
459
|
const rewriteParams = {
|
|
625
460
|
...params,
|
|
626
461
|
...conditionParams
|
|
627
462
|
};
|
|
628
|
-
return substituteAndSanitizeRewriteDestination(serializeRewriteDestinationTemplate(rewrite.destination), rewriteParams);
|
|
463
|
+
return substituteAndSanitizeRewriteDestination(serializeRewriteDestinationTemplate(rewrite.destination), rewriteParams, unmatched.filter((key) => !(key in conditionParams)));
|
|
629
464
|
}
|
|
630
465
|
}
|
|
631
466
|
return null;
|
|
@@ -663,26 +498,100 @@ function matchesRewriteSource(pathname, rewrite, basePathState = _BASEPATH_DEFAU
|
|
|
663
498
|
function substituteAndSanitizeDestination(destination, params, kind) {
|
|
664
499
|
return sanitizeDestination(substituteDestinationParams(destination, params, kind));
|
|
665
500
|
}
|
|
666
|
-
|
|
501
|
+
/**
|
|
502
|
+
* Prepare a redirect destination template as Next.js does before substituting
|
|
503
|
+
* params. processRoutes (load-custom-routes.ts) prefixes a local destination
|
|
504
|
+
* with the basePath (a bare `/` becomes the basePath, except on the
|
|
505
|
+
* default-locale variant), then parseDestination (prepare-destination.ts) parses it
|
|
506
|
+
* with the URL parser, its param tokens escaped so they survive. This trims
|
|
507
|
+
* whitespace, resolves dot segments and backslashes, percent-encodes the path
|
|
508
|
+
* and hash, punycodes the host, drops an empty query or hash, and throws (a
|
|
509
|
+
* 500) on an invalid absolute URL. Captures are substituted afterwards, so the
|
|
510
|
+
* parser never sees them. The query text is kept verbatim, as
|
|
511
|
+
* preserveRedirectDestinationQuery emits it.
|
|
512
|
+
*/
|
|
513
|
+
function parseRedirectDestinationTemplate(redirect, params, { basePath, hadBasePath }) {
|
|
514
|
+
let template = redirect.destination;
|
|
515
|
+
const isLocal = template.startsWith("/");
|
|
516
|
+
if (isLocal && basePath && hadBasePath) template = template === "/" && !redirect.defaultLocaleVariant ? basePath : basePath + template;
|
|
517
|
+
template = template.replace(LOCATION_STRIPPED_RE, "");
|
|
518
|
+
let marker = "__ESC_COLON_";
|
|
519
|
+
while (template.toLowerCase().includes(marker.toLowerCase())) marker = `_${marker}`;
|
|
520
|
+
const paramValues = Object.values(params);
|
|
521
|
+
let literalColon = "__ESC_LITERAL_COLON_";
|
|
522
|
+
while (template.includes(literalColon) || paramValues.some((value) => value.includes(literalColon))) literalColon = `_${literalColon}`;
|
|
523
|
+
const keys = Object.keys(params).sort((a, b) => b.length - a.length);
|
|
524
|
+
const keyPattern = keys.map((key) => key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|");
|
|
525
|
+
const escaped = keys.length === 0 ? template : template.replace(new RegExp(`\\\\.|:(${keyPattern})(?![A-Za-z0-9_])`, "gs"), (match, key) => key ? `${marker}${key}` : match);
|
|
526
|
+
const consumeEscapes = (value) => value.replace(/\\(.)/gs, (_, char) => char === ":" ? literalColon : char);
|
|
527
|
+
let url;
|
|
528
|
+
try {
|
|
529
|
+
url = isLocal ? new URL(`http://n${escaped}`) : new URL(escaped);
|
|
530
|
+
} catch {
|
|
531
|
+
return {
|
|
532
|
+
template,
|
|
533
|
+
literalColon,
|
|
534
|
+
parsed: false
|
|
535
|
+
};
|
|
536
|
+
}
|
|
537
|
+
const hash = url.hash;
|
|
538
|
+
url.search = "";
|
|
539
|
+
url.hash = "";
|
|
540
|
+
const hashIndex = template.indexOf("#");
|
|
541
|
+
const beforeHash = hashIndex === -1 ? template : template.slice(0, hashIndex);
|
|
542
|
+
const queryIndex = beforeHash.indexOf("?");
|
|
543
|
+
const query = queryIndex === -1 ? "" : beforeHash.slice(queryIndex);
|
|
544
|
+
let base = isLocal ? url.pathname : url.href;
|
|
545
|
+
if (!isLocal && (url.username || url.password)) {
|
|
546
|
+
const auth = url.username ? `${encodeURIComponent(url.password ? `${url.username}:${url.password}` : url.username).replace(/%3A/i, ":")}@` : "";
|
|
547
|
+
url.username = "";
|
|
548
|
+
url.password = "";
|
|
549
|
+
base = url.href.replace("//", `//${auth}`);
|
|
550
|
+
}
|
|
551
|
+
if (!isLocal && !SPECIAL_SCHEME_RE.test(url.protocol)) base = base.slice(0, base.length - url.pathname.length) + consumeEscapes(url.pathname);
|
|
552
|
+
const markerRe = new RegExp(`${marker}(${keyPattern})`, "gi");
|
|
553
|
+
const unescape = (value) => keys.length === 0 ? value : value.replace(markerRe, (_, key) => `:${keys.includes(key) ? key : keys.find((k) => k.toLowerCase() === key.toLowerCase())}`);
|
|
667
554
|
return {
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
555
|
+
template: `${unescape(base)}${/^\?&*$/.test(query) ? "" : query}${unescape(consumeEscapes(hash))}`,
|
|
556
|
+
literalColon,
|
|
557
|
+
parsed: true
|
|
558
|
+
};
|
|
559
|
+
}
|
|
560
|
+
const SPECIAL_SCHEME_RE = /^(?:https?|wss?|ftp|file):$/;
|
|
561
|
+
const REDIRECT_ORIGIN_RE = /^[A-Za-z][A-Za-z0-9+.-]*:\/\/[^/?#]*/;
|
|
562
|
+
/**
|
|
563
|
+
* Next.js resolve-routes.ts runs normalizeRepeatedSlashes on the prepared
|
|
564
|
+
* destination's pathname, after params are substituted: backslashes become
|
|
565
|
+
* `/` and runs of slashes collapse, so a basePath-prefixed `//target`
|
|
566
|
+
* becomes `/docs/target`. `destination` starts at the pathname.
|
|
567
|
+
*/
|
|
568
|
+
function normalizeRedirectPathnameSlashes(destination) {
|
|
569
|
+
return destination.replace(/^[^?#]*/, (pathname) => pathname.replace(/\\/g, "/").replace(/\/\/+/g, "/"));
|
|
570
|
+
}
|
|
571
|
+
function resolveRedirectMatch(redirect, params, basePathState) {
|
|
572
|
+
const { template: destination, literalColon, parsed } = parseRedirectDestinationTemplate(redirect, params, basePathState);
|
|
573
|
+
const origin = REDIRECT_ORIGIN_RE.exec(destination)?.[0] ?? "";
|
|
574
|
+
return {
|
|
575
|
+
destination: (!parsed ? substituteAndSanitizeDestination(destination, params, "redirect") : origin ? substituteDestinationParams(origin, params, "redirect") + normalizeRedirectPathnameSlashes(substituteDestinationParams(destination.slice(origin.length), params, "redirect")) : normalizeRedirectPathnameSlashes(substituteAndSanitizeDestination(destination, params, "redirect"))).replaceAll(literalColon, ":"),
|
|
576
|
+
statusCode: redirect.statusCode || (redirect.permanent ? 308 : 307),
|
|
577
|
+
destinationQuery: substituteRedirectDestinationQuery(destination, params)
|
|
671
578
|
};
|
|
672
579
|
}
|
|
673
580
|
/**
|
|
674
581
|
* Match Next.js's rewrite-specific prepareDestination behavior: source params
|
|
675
582
|
* that are not consumed by the destination path/host are exposed to the target
|
|
676
|
-
* page through query.
|
|
583
|
+
* page through query. Optional params that did not match are not params at
|
|
584
|
+
* all in Next.js, so they are neither appended nor count as consumed.
|
|
677
585
|
*
|
|
678
586
|
* https://github.com/vercel/next.js/blob/canary/packages/next/src/shared/lib/router/utils/prepare-destination.ts
|
|
679
587
|
*/
|
|
680
|
-
function substituteAndSanitizeRewriteDestination(destination, params) {
|
|
588
|
+
function substituteAndSanitizeRewriteDestination(destination, params, unmatchedParams) {
|
|
681
589
|
const rewritten = substituteAndSanitizeDestination(destination, params, "rewrite");
|
|
682
|
-
|
|
590
|
+
const matchedParams = unmatchedParams.length === 0 ? params : Object.fromEntries(Object.entries(params).filter(([key]) => !unmatchedParams.includes(key)));
|
|
591
|
+
if (!shouldAppendRewriteParamsToQuery(destination, matchedParams)) return rewritten;
|
|
683
592
|
const existingQueryKeys = getDestinationQueryKeys(destination);
|
|
684
593
|
const paramsToAppend = [];
|
|
685
|
-
for (const [key, value] of Object.entries(
|
|
594
|
+
for (const [key, value] of Object.entries(matchedParams)) {
|
|
686
595
|
if (key === "nextInternalLocale" || existingQueryKeys.has(key)) continue;
|
|
687
596
|
paramsToAppend.push([key, value]);
|
|
688
597
|
}
|
|
@@ -808,6 +717,22 @@ function preserveRedirectDestinationQuery(destination, requestSearch, destinatio
|
|
|
808
717
|
}).flat().join("&");
|
|
809
718
|
return mergedQuery === "" ? `${pathPart}${hash}` : `${pathPart}?${mergedQuery}${hash}`;
|
|
810
719
|
}
|
|
720
|
+
const LOCATION_STRIPPED_RE = /^[\u0000- ]+|[\u0000- ]+$|[\t\n\r]/g;
|
|
721
|
+
const LOCATION_UNSAFE_RE = /[\u0000-\u0008\u000A-\u001F\u007F]|[^\u0000-\u007F]/gu;
|
|
722
|
+
const LONE_SURROGATE_RE = /[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/g;
|
|
723
|
+
/**
|
|
724
|
+
* Percent-encode what a config-redirect `Location` header cannot carry.
|
|
725
|
+
*
|
|
726
|
+
* The destination template was already parsed like a URL by matchRedirect, so
|
|
727
|
+
* its literal path, hash and host are encoded as Next.js sends them. Captures
|
|
728
|
+
* and the destination query are inserted verbatim, like Next.js, so they can
|
|
729
|
+
* still hold control or non-ASCII characters. Next.js writes those raw and its
|
|
730
|
+
* Node server answers 500 for a character above U+00FF (the Headers
|
|
731
|
+
* constructor throws the same way); vinext percent-encodes them instead.
|
|
732
|
+
*/
|
|
733
|
+
function encodeRedirectLocation(location) {
|
|
734
|
+
return location.replace(LONE_SURROGATE_RE, "�").replace(LOCATION_UNSAFE_RE, encodeURIComponent);
|
|
735
|
+
}
|
|
811
736
|
function parseExternalRewriteUrl(externalUrl) {
|
|
812
737
|
try {
|
|
813
738
|
return new URL(externalUrl);
|
|
@@ -898,24 +823,119 @@ async function proxyExternalRequest(request, externalUrl) {
|
|
|
898
823
|
* when evaluating headers, so this parameter is required.
|
|
899
824
|
*/
|
|
900
825
|
function matchHeaders(pathname, headers, ctx, basePathState = _BASEPATH_DEFAULT, onRuleSourceMatch) {
|
|
901
|
-
const pathnameHadTrailingSlash = pathname.length > 1 && pathname.endsWith("/");
|
|
902
|
-
pathname = stripTrailingSlashForConfigMatch(pathname);
|
|
903
826
|
const result = [];
|
|
904
827
|
for (const rule of headers) {
|
|
905
828
|
if (!shouldEvaluateRule(rule.basePath, basePathState)) continue;
|
|
906
|
-
const
|
|
907
|
-
const
|
|
908
|
-
if (
|
|
829
|
+
const compiledSource = compileConfigSource(rule.source);
|
|
830
|
+
const sourceMatch = compiledSource?.re.exec(pathname);
|
|
831
|
+
if (compiledSource && sourceMatch) {
|
|
909
832
|
onRuleSourceMatch?.(rule);
|
|
910
833
|
if (rule.has || rule.missing) {
|
|
911
834
|
if (!checkHasConditions(rule.has, rule.missing, ctx)) continue;
|
|
912
835
|
}
|
|
913
|
-
|
|
836
|
+
if (!rule.headers.some((header) => header.key.includes(":") || header.value.includes(":"))) {
|
|
837
|
+
result.push(...rule.headers);
|
|
838
|
+
continue;
|
|
839
|
+
}
|
|
840
|
+
const params = collectHeaderSourceParams(sourceMatch, compiledSource.keys);
|
|
841
|
+
if (rule.has) collectHeaderHasParams(rule.has, ctx, params);
|
|
842
|
+
result.push(...substituteHeaderParams(rule.headers, params));
|
|
914
843
|
}
|
|
915
844
|
}
|
|
916
845
|
return result;
|
|
917
846
|
}
|
|
918
847
|
/**
|
|
848
|
+
* Collect source params like Next.js's `getPathMatch` with
|
|
849
|
+
* `removeUnnamedParams`: path-to-regexp's `regexpToFunction` keeps captures
|
|
850
|
+
* raw, splits `*`/`+` captures on the key's prefix and suffix, and omits
|
|
851
|
+
* groups that did not participate.
|
|
852
|
+
*/
|
|
853
|
+
function collectHeaderSourceParams(match, keys) {
|
|
854
|
+
const params = _emptyParams();
|
|
855
|
+
for (let index = 1; index < match.length; index++) {
|
|
856
|
+
const capture = match[index];
|
|
857
|
+
const key = keys[index - 1];
|
|
858
|
+
if (capture === void 0 || !key || typeof key.name === "number") continue;
|
|
859
|
+
params[key.name] = key.modifier === "*" || key.modifier === "+" ? capture.split(key.prefix + key.suffix) : capture;
|
|
860
|
+
}
|
|
861
|
+
return params;
|
|
862
|
+
}
|
|
863
|
+
/**
|
|
864
|
+
* Add `has` captures like Next.js's `matchHas`, after checkHasConditions has
|
|
865
|
+
* accepted the rule: a condition without a value exposes the matched value
|
|
866
|
+
* under its key (letters only), a value regex exposes its named groups, and a
|
|
867
|
+
* host regex without named groups exposes the matched host as `host`.
|
|
868
|
+
*
|
|
869
|
+
* https://github.com/vercel/next.js/blob/v16.2.7/packages/next/src/shared/lib/router/utils/prepare-destination.ts
|
|
870
|
+
*/
|
|
871
|
+
function collectHeaderHasParams(has, ctx, params) {
|
|
872
|
+
for (const condition of has) {
|
|
873
|
+
let value;
|
|
874
|
+
switch (condition.type) {
|
|
875
|
+
case "header":
|
|
876
|
+
value = ctx.headers.get(condition.key) ?? void 0;
|
|
877
|
+
break;
|
|
878
|
+
case "cookie":
|
|
879
|
+
value = Object.hasOwn(ctx.cookies, condition.key) ? ctx.cookies[condition.key] : void 0;
|
|
880
|
+
break;
|
|
881
|
+
case "query": {
|
|
882
|
+
const values = ctx.query.getAll(condition.key);
|
|
883
|
+
value = values.length > 1 ? values : values[0];
|
|
884
|
+
break;
|
|
885
|
+
}
|
|
886
|
+
case "host": value = ctx.host;
|
|
887
|
+
}
|
|
888
|
+
if (!value) continue;
|
|
889
|
+
if (!condition.value) {
|
|
890
|
+
if (condition.type !== "host") params[condition.key.replace(/[^A-Za-z]/g, "")] = value;
|
|
891
|
+
continue;
|
|
892
|
+
}
|
|
893
|
+
const match = _cachedConditionRegex(condition.value)?.exec(Array.isArray(value) ? value[value.length - 1] : value);
|
|
894
|
+
if (!match) continue;
|
|
895
|
+
if (match.groups) Object.assign(params, match.groups);
|
|
896
|
+
else if (condition.type === "host" && match[0]) params.host = match[0];
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
const _warnedHeaderParamTemplates = /* @__PURE__ */ new WeakSet();
|
|
900
|
+
/**
|
|
901
|
+
* Substitute params into header keys and values like Next.js's
|
|
902
|
+
* `compileNonPath`, with params inserted verbatim. Source captures are the raw
|
|
903
|
+
* percent-encoded path text, as in Next.js, but `has` captures from decoded
|
|
904
|
+
* cookies or query values can carry characters a header cannot.
|
|
905
|
+
*
|
|
906
|
+
* Next.js fails the whole request when compiling throws (a repeated param
|
|
907
|
+
* used without `*`/`+`, or a has group that did not participate) or when the
|
|
908
|
+
* result is not a valid header. Requests can trigger both, so vinext instead
|
|
909
|
+
* omits only the affected header and logs once per header template.
|
|
910
|
+
*/
|
|
911
|
+
function substituteHeaderParams(headers, params) {
|
|
912
|
+
if (Object.keys(params).length === 0) return headers;
|
|
913
|
+
const result = [];
|
|
914
|
+
for (const header of headers) {
|
|
915
|
+
let key;
|
|
916
|
+
let value;
|
|
917
|
+
try {
|
|
918
|
+
key = compileHeaderParamTemplate(header.key, params);
|
|
919
|
+
value = compileHeaderParamTemplate(header.value, params);
|
|
920
|
+
} catch (error) {
|
|
921
|
+
warnHeaderParamTemplate(header, error instanceof Error ? error.message : String(error));
|
|
922
|
+
continue;
|
|
923
|
+
}
|
|
924
|
+
if (key === header.key && value === header.value) result.push(header);
|
|
925
|
+
else if (isValidHeaderPair(key, value)) result.push({
|
|
926
|
+
key,
|
|
927
|
+
value
|
|
928
|
+
});
|
|
929
|
+
else warnHeaderParamTemplate(header, "the substituted header is not a valid HTTP header");
|
|
930
|
+
}
|
|
931
|
+
return result;
|
|
932
|
+
}
|
|
933
|
+
function warnHeaderParamTemplate(header, reason) {
|
|
934
|
+
if (_warnedHeaderParamTemplates.has(header)) return;
|
|
935
|
+
_warnedHeaderParamTemplates.add(header);
|
|
936
|
+
console.warn(`[vinext] Omitting headers() header "${header.key}: ${header.value}" from a response: ${reason}.`);
|
|
937
|
+
}
|
|
938
|
+
/**
|
|
919
939
|
* Escape a string for inclusion in a regex character class / alternation.
|
|
920
940
|
* Mirrors `escape-string-regexp` semantics used by Next.js's processRoutes.
|
|
921
941
|
*/
|
|
@@ -936,17 +956,19 @@ function _escapeRegexString(value) {
|
|
|
936
956
|
* starts with `/:nextInternalLocale(en|sv|nl)` so that locale-prefixed
|
|
937
957
|
* URLs match. For redirects only, a second variant prefixed with
|
|
938
958
|
* `/${defaultLocale}` is also emitted, matching Next.js exactly.
|
|
939
|
-
* -
|
|
940
|
-
*
|
|
941
|
-
*
|
|
942
|
-
*
|
|
943
|
-
*
|
|
944
|
-
*
|
|
945
|
-
*
|
|
946
|
-
*
|
|
947
|
-
*
|
|
948
|
-
*
|
|
949
|
-
*
|
|
959
|
+
* - Headers get only that variant, exactly like Next.js. Every header
|
|
960
|
+
* matcher caller splices the (domain-aware) default locale into
|
|
961
|
+
* unprefixed request paths first (`normalizeDefaultLocalePathname`,
|
|
962
|
+
* mirroring `resolve-routes.ts`), so `/about` is matched as `/en/about`.
|
|
963
|
+
* `/_next/*` paths are left unprefixed and therefore only match
|
|
964
|
+
* `locale: false` rules, as in Next.js.
|
|
965
|
+
* - **Vinext divergence (redirects/rewrites only)**: we ALSO retain the
|
|
966
|
+
* original (unprefixed) source, appended LAST so the locale-aware
|
|
967
|
+
* variants win when both forms could match. Their callers normalise
|
|
968
|
+
* default-locale paths too, so this is a legacy fallback. Headers never
|
|
969
|
+
* get it: it would apply rules Next.js skips (`/((?!api).*)` would match
|
|
970
|
+
* `/fr/api/x` as `fr/api/x`), and default-locale requests would match
|
|
971
|
+
* both variants, appending additive headers such as `Set-Cookie` twice.
|
|
950
972
|
*
|
|
951
973
|
* Destinations that are local (start with `/`) are similarly rewritten with
|
|
952
974
|
* `/:nextInternalLocale` for the locale-capture variant so the locale
|
|
@@ -973,7 +995,8 @@ function applyLocaleToRoutes(routes, i18n, type, options = {}) {
|
|
|
973
995
|
const localizedSource = `/${locale}${suffixFor(r.source)}`;
|
|
974
996
|
out.push({
|
|
975
997
|
...r,
|
|
976
|
-
source: localizedSource
|
|
998
|
+
source: localizedSource,
|
|
999
|
+
...type === "redirect" ? { defaultLocaleVariant: true } : {}
|
|
977
1000
|
});
|
|
978
1001
|
}
|
|
979
1002
|
const internalSource = `${internalLocale}${suffixFor(r.source)}`;
|
|
@@ -985,9 +1008,9 @@ function applyLocaleToRoutes(routes, i18n, type, options = {}) {
|
|
|
985
1008
|
};
|
|
986
1009
|
if ("destination" in internalRoute && internalDestination !== void 0) internalRoute.destination = internalDestination;
|
|
987
1010
|
out.push(internalRoute);
|
|
988
|
-
out.push(r);
|
|
1011
|
+
if (type !== "header") out.push(r);
|
|
989
1012
|
}
|
|
990
1013
|
return out;
|
|
991
1014
|
}
|
|
992
1015
|
//#endregion
|
|
993
|
-
export { applyLocaleToRoutes, applyMiddlewareRequestHeaders, checkHasConditions,
|
|
1016
|
+
export { applyLocaleToRoutes, applyMiddlewareRequestHeaders, checkHasConditions, configSourceError, encodeRedirectLocation, isExternalUrl, matchConfigPattern, matchHeaders, matchRedirect, matchRewrite, matchesRewriteSource, normalizeHost, parseCookies, preserveRedirectDestinationQuery, proxyExternalRequest, requestContextFromRequest, sanitizeDestination };
|