vinext 1.0.1 → 1.2.0
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 +93 -10
- package/dist/build/app-page-static-eligibility.d.ts +15 -0
- package/dist/build/app-page-static-eligibility.js +82 -0
- package/dist/build/client-build-config.d.ts +10 -0
- package/dist/build/client-build-config.js +18 -2
- package/dist/build/pages-client-assets-module.d.ts +8 -0
- package/dist/build/pages-client-assets-module.js +21 -1
- package/dist/build/prerender-paths.js +8 -81
- package/dist/build/prerender.js +33 -8
- package/dist/build/run-prerender.js +1 -1
- package/dist/build/server-manifest.d.ts +7 -0
- package/dist/build/server-manifest.js +11 -1
- package/dist/build/ssr-manifest.d.ts +2 -0
- package/dist/build/ssr-manifest.js +6 -2
- package/dist/cache/cache-adapters-virtual.d.ts +7 -1
- package/dist/cache/cache-adapters-virtual.js +3 -3
- package/dist/check.js +7 -6
- package/dist/cli.js +2 -1
- package/dist/client/client-redirect-matcher.d.ts +14 -0
- package/dist/client/client-redirect-matcher.js +37 -0
- package/dist/client/client-redirects.d.ts +27 -0
- package/dist/client/client-redirects.js +28 -0
- package/dist/client/client-rewrites.d.ts +2 -1
- package/dist/client/client-rewrites.js +1 -1
- package/dist/client/navigation-runtime.d.ts +11 -0
- package/dist/client/navigation-runtime.js +1 -1
- package/dist/config/config-matchers.d.ts +26 -11
- package/dist/config/config-matchers.js +81 -82
- package/dist/config/destination-params.d.ts +47 -0
- package/dist/config/destination-params.js +116 -0
- package/dist/config/next-config.d.ts +14 -0
- package/dist/config/next-config.js +21 -3
- package/dist/entries/app-rsc-entry.d.ts +6 -0
- package/dist/entries/app-rsc-entry.js +84 -49
- package/dist/entries/pages-client-entry.js +3 -1
- package/dist/entries/pages-server-entry.js +13 -37
- package/dist/index.d.ts +7 -2
- package/dist/index.js +193 -73
- package/dist/init-cloudflare.d.ts +9 -0
- package/dist/init-cloudflare.js +107 -31
- package/dist/init-platform.d.ts +4 -0
- package/dist/init-platform.js +27 -2
- package/dist/init.d.ts +1 -0
- package/dist/init.js +67 -3
- package/dist/plugins/ast-scope.d.ts +7 -0
- package/dist/plugins/ast-scope.js +59 -3
- package/dist/plugins/cache-flight-codec.d.ts +19 -0
- package/dist/plugins/cache-flight-codec.js +68 -0
- package/dist/plugins/commonjs-esm-facade.d.ts +35 -0
- package/dist/plugins/commonjs-esm-facade.js +80 -0
- package/dist/plugins/dynamic-preload-metadata.d.ts +1 -1
- package/dist/plugins/dynamic-preload-metadata.js +9 -8
- package/dist/plugins/fonts.d.ts +8 -11
- package/dist/plugins/fonts.js +71 -34
- package/dist/plugins/ignore-dynamic-requests.d.ts +1 -1
- package/dist/plugins/ignore-dynamic-requests.js +3 -4
- package/dist/plugins/middleware-server-only.d.ts +5 -4
- package/dist/plugins/middleware-server-only.js +8 -5
- package/dist/plugins/pages-node-externals.js +1 -1
- package/dist/plugins/rsc-scan-glob-imports.d.ts +19 -0
- package/dist/plugins/rsc-scan-glob-imports.js +50 -0
- package/dist/plugins/strip-server-exports.js +262 -98
- package/dist/plugins/transform-result.d.ts +9 -5
- package/dist/plugins/transitive-externals.js +1 -1
- package/dist/plugins/typeof-window.d.ts +2 -2
- package/dist/plugins/use-cache-callable.js +8 -2
- package/dist/plugins/worker-server-only-imports.d.ts +20 -0
- package/dist/plugins/worker-server-only-imports.js +31 -0
- package/dist/plugins/worker-use-server.d.ts +25 -0
- package/dist/plugins/worker-use-server.js +129 -0
- package/dist/routing/file-matcher.d.ts +1 -0
- package/dist/routing/file-matcher.js +1 -1
- package/dist/server/api-handler.d.ts +1 -0
- package/dist/server/api-handler.js +19 -8
- package/dist/server/app-browser-action-result.d.ts +1 -1
- package/dist/server/app-browser-action-result.js +9 -2
- package/dist/server/app-browser-entry.js +11 -7
- package/dist/server/app-browser-history-controller.d.ts +2 -0
- package/dist/server/app-browser-history-controller.js +8 -0
- package/dist/server/app-browser-interception-context.js +26 -2
- package/dist/server/app-browser-navigation-controller.d.ts +7 -1
- package/dist/server/app-browser-navigation-controller.js +94 -11
- package/dist/server/app-browser-server-action-client.js +1 -1
- package/dist/server/app-fallback-renderer.d.ts +2 -0
- package/dist/server/app-fallback-renderer.js +1 -0
- package/dist/server/app-history-state.d.ts +3 -0
- package/dist/server/app-history-state.js +7 -0
- package/dist/server/app-middleware.d.ts +11 -0
- package/dist/server/app-middleware.js +19 -3
- package/dist/server/app-optimistic-routing.js +1 -1
- package/dist/server/app-page-boundary-render.d.ts +5 -0
- package/dist/server/app-page-boundary-render.js +6 -4
- package/dist/server/app-page-cache-finalizer.d.ts +11 -0
- package/dist/server/app-page-cache-finalizer.js +41 -7
- package/dist/server/app-page-cache-render.d.ts +18 -0
- package/dist/server/app-page-cache-render.js +63 -43
- package/dist/server/app-page-cache.d.ts +6 -1
- package/dist/server/app-page-cache.js +28 -8
- package/dist/server/app-page-dispatch.d.ts +12 -2
- package/dist/server/app-page-dispatch.js +51 -33
- package/dist/server/app-page-element-builder.d.ts +7 -0
- package/dist/server/app-page-element-builder.js +27 -42
- package/dist/server/app-page-execution.d.ts +15 -12
- package/dist/server/app-page-execution.js +30 -40
- package/dist/server/app-page-head.d.ts +5 -0
- package/dist/server/app-page-head.js +9 -3
- package/dist/server/app-page-ppr-runtime.js +1 -1
- package/dist/server/app-page-probe.d.ts +0 -109
- package/dist/server/app-page-probe.js +3 -136
- package/dist/server/app-page-render-identity.d.ts +0 -1
- package/dist/server/app-page-render-identity.js +1 -1
- package/dist/server/app-page-render-observation.js +3 -3
- package/dist/server/app-page-render.d.ts +13 -5
- package/dist/server/app-page-render.js +219 -119
- package/dist/server/app-page-request.d.ts +0 -1
- package/dist/server/app-page-request.js +54 -17
- package/dist/server/app-page-response.d.ts +4 -3
- package/dist/server/app-page-response.js +4 -3
- package/dist/server/app-page-route-wiring.d.ts +17 -5
- package/dist/server/app-page-route-wiring.js +57 -35
- package/dist/server/app-page-rsc-render-status.d.ts +48 -0
- package/dist/server/app-page-rsc-render-status.js +54 -0
- package/dist/server/app-page-stream.d.ts +15 -8
- package/dist/server/app-page-stream.js +6 -0
- package/dist/server/app-pages-bridge.d.ts +1 -1
- package/dist/server/app-pages-bridge.js +2 -3
- package/dist/server/app-prerender-endpoints.js +9 -6
- package/dist/server/app-request-stage-dispatch.js +7 -3
- package/dist/server/app-request-stage-independent-entry.js +29 -9
- package/dist/server/app-response-header-provenance.d.ts +2 -0
- package/dist/server/app-response-header-provenance.js +10 -4
- package/dist/server/app-response-stage-entry.js +10 -2
- package/dist/server/app-route-handler-cache.d.ts +1 -0
- package/dist/server/app-route-handler-cache.js +1 -0
- package/dist/server/app-route-handler-dispatch.d.ts +1 -0
- package/dist/server/app-route-handler-dispatch.js +6 -3
- package/dist/server/app-route-handler-execution.d.ts +1 -0
- package/dist/server/app-route-handler-execution.js +1 -0
- package/dist/server/app-route-handler-runtime.d.ts +4 -1
- package/dist/server/app-route-handler-runtime.js +45 -24
- package/dist/server/app-router-entry.js +27 -8
- package/dist/server/app-rsc-cache-busting.js +1 -1
- package/dist/server/app-rsc-errors.js +20 -16
- package/dist/server/app-rsc-handler.d.ts +11 -0
- package/dist/server/app-rsc-handler.js +291 -125
- package/dist/server/app-rsc-request-normalization.d.ts +3 -1
- package/dist/server/app-rsc-request-normalization.js +4 -2
- package/dist/server/app-rsc-response-stage.d.ts +1 -1
- package/dist/server/app-rsc-response-stage.js +10 -6
- package/dist/server/app-rsc-route-matching.d.ts +9 -1
- package/dist/server/app-rsc-route-matching.js +36 -19
- package/dist/server/app-segment-config.d.ts +2 -1
- package/dist/server/app-server-action-execution.d.ts +2 -1
- package/dist/server/app-server-action-execution.js +62 -23
- package/dist/server/app-ssr-entry.d.ts +3 -2
- package/dist/server/app-ssr-entry.js +8 -5
- package/dist/server/app-ssr-stream.d.ts +6 -1
- package/dist/server/app-ssr-stream.js +34 -15
- package/dist/server/app-worker-stages.d.ts +7 -2
- package/dist/server/app-worker-stages.js +4 -4
- package/dist/server/cacheability-request.js +11 -7
- package/dist/server/client-build-files.d.ts +16 -0
- package/dist/server/client-build-files.js +36 -0
- package/dist/server/client-reuse-manifest.js +1 -1
- package/dist/server/config-headers.js +2 -0
- package/dist/server/dev-server.js +50 -29
- package/dist/server/dev-stack-sourcemap.js +18 -23
- package/dist/server/document-initial-head.d.ts +0 -11
- package/dist/server/document-initial-head.js +1 -1
- package/dist/server/forwarded-middleware-context.d.ts +5 -0
- package/dist/server/forwarded-middleware-context.js +22 -0
- package/dist/server/headers.d.ts +18 -1
- package/dist/server/headers.js +19 -2
- package/dist/server/http-conditional.d.ts +11 -0
- package/dist/server/http-conditional.js +10 -1
- package/dist/server/http-error-responses.d.ts +1 -1
- package/dist/server/image-optimization.d.ts +54 -0
- package/dist/server/image-optimization.js +118 -9
- package/dist/server/isr-cache.d.ts +10 -0
- package/dist/server/isr-cache.js +43 -8
- package/dist/server/metadata-route-response.js +9 -8
- package/dist/server/middleware-matcher-pattern.js +8 -4
- package/dist/server/middleware-matcher.d.ts +2 -0
- package/dist/server/middleware-matcher.js +23 -2
- package/dist/server/middleware-response-headers.js +2 -0
- package/dist/server/middleware-runtime.d.ts +13 -0
- package/dist/server/middleware-runtime.js +33 -20
- package/dist/server/middleware.d.ts +1 -1
- package/dist/server/middleware.js +3 -1
- package/dist/server/multi-stage.d.ts +19 -0
- package/dist/server/navigation-planner.js +1 -1
- package/dist/server/node-response-signal.d.ts +16 -0
- package/dist/server/node-response-signal.js +26 -0
- package/dist/server/normalize-path.d.ts +0 -13
- package/dist/server/normalize-path.js +1 -34
- package/dist/server/open-redirect.d.ts +47 -0
- package/dist/server/open-redirect.js +74 -1
- package/dist/server/pages-api-route.d.ts +3 -2
- package/dist/server/pages-api-route.js +4 -3
- package/dist/server/pages-cache-tag.d.ts +12 -0
- package/dist/server/pages-cache-tag.js +19 -0
- package/dist/server/pages-client-assets.d.ts +2 -0
- package/dist/server/pages-data-route.d.ts +10 -0
- package/dist/server/pages-data-route.js +19 -2
- package/dist/server/pages-document-asset-props.d.ts +5 -1
- package/dist/server/pages-document-asset-props.js +13 -5
- package/dist/server/pages-document-splice.d.ts +19 -0
- package/dist/server/pages-document-splice.js +55 -0
- package/dist/server/pages-i18n.d.ts +12 -1
- package/dist/server/pages-i18n.js +18 -4
- package/dist/server/pages-node-compat.d.ts +16 -5
- package/dist/server/pages-node-compat.js +20 -12
- package/dist/server/pages-page-data.d.ts +32 -24
- package/dist/server/pages-page-data.js +50 -120
- package/dist/server/pages-page-handler.d.ts +0 -6
- package/dist/server/pages-page-handler.js +209 -130
- package/dist/server/pages-page-response.d.ts +12 -6
- package/dist/server/pages-page-response.js +41 -34
- package/dist/server/pages-request-pipeline.d.ts +10 -2
- package/dist/server/pages-request-pipeline.js +37 -18
- package/dist/server/pages-request-stage-entry.d.ts +6 -0
- package/dist/server/pages-request-stage-entry.js +79 -16
- package/dist/server/pages-response-stage-entry.js +4 -0
- package/dist/server/pages-revalidate.js +1 -1
- package/dist/server/pages-router-entry.js +4 -3
- package/dist/server/prerender-manifest.d.ts +3 -3
- package/dist/server/prerender-manifest.js +4 -3
- package/dist/server/prerender-work-unit-setup.js +4 -0
- package/dist/server/prod-server.d.ts +20 -7
- package/dist/server/prod-server.js +343 -129
- package/dist/server/proper-error.d.ts +4 -0
- package/dist/server/proper-error.js +31 -0
- package/dist/server/request-pipeline.d.ts +24 -9
- package/dist/server/request-pipeline.js +24 -9
- package/dist/server/response-compression.d.ts +43 -0
- package/dist/server/response-compression.js +111 -0
- package/dist/server/revalidation-request.d.ts +1 -0
- package/dist/server/revalidation-request.js +1 -1
- package/dist/server/rsc-stream-hints.js +31 -2
- package/dist/server/seed-cache.d.ts +1 -0
- package/dist/server/seed-cache.js +15 -11
- package/dist/server/server-reference-loader.d.ts +4 -0
- package/dist/server/server-reference-loader.js +29 -0
- package/dist/server/socket-error-backstop.d.ts +23 -1
- package/dist/server/socket-error-backstop.js +69 -17
- package/dist/server/static-file-signal.d.ts +15 -4
- package/dist/server/static-file-signal.js +46 -12
- package/dist/server/worker-image-optimization.d.ts +34 -0
- package/dist/server/worker-image-optimization.js +86 -0
- package/dist/server/worker-stages.d.ts +1 -1
- package/dist/server/worker-stages.js +2 -2
- package/dist/server/worker-utils.d.ts +8 -3
- package/dist/server/worker-utils.js +12 -7
- package/dist/shims/app-router-scroll.js +4 -1
- package/dist/shims/app-router-tree-context.d.ts +5 -0
- package/dist/shims/app-router-tree-context.js +27 -0
- package/dist/shims/cache-adapter-instantiate.d.ts +50 -0
- package/dist/shims/cache-adapter-instantiate.js +118 -0
- package/dist/shims/cache-callable-runtime.d.ts +6 -42
- package/dist/shims/cache-callable-runtime.js +65 -174
- package/dist/shims/cache-flight-arguments.d.ts +22 -0
- package/dist/shims/cache-flight-arguments.js +56 -0
- package/dist/shims/cache-handler.js +1 -9
- package/dist/shims/cache-request-state.d.ts +15 -0
- package/dist/shims/cache-request-state.js +31 -8
- package/dist/shims/cache-runtime.d.ts +12 -20
- package/dist/shims/cache-runtime.js +166 -225
- package/dist/shims/cache.d.ts +4 -4
- package/dist/shims/cache.js +44 -16
- package/dist/shims/cacheability-classification.d.ts +7 -0
- package/dist/shims/cdn-cache.d.ts +8 -0
- package/dist/shims/cdn-cache.js +17 -1
- package/dist/shims/disable-smooth-scroll.d.ts +3 -0
- package/dist/shims/disable-smooth-scroll.js +36 -0
- package/dist/shims/document-placeholders.d.ts +19 -0
- package/dist/shims/document-placeholders.js +45 -0
- package/dist/shims/document.js +21 -5
- package/dist/shims/dynamic-preload-chunks.d.ts +1 -0
- package/dist/shims/dynamic-preload-chunks.js +13 -9
- package/dist/shims/dynamic.d.ts +1 -1
- package/dist/shims/dynamic.js +60 -8
- package/dist/shims/error-boundary-navigation.d.ts +7 -0
- package/dist/shims/error-boundary-navigation.js +19 -1
- package/dist/shims/error-boundary.d.ts +10 -10
- package/dist/shims/error-boundary.js +26 -7
- package/dist/shims/fetch-cache-state.d.ts +66 -0
- package/dist/shims/fetch-cache-state.js +92 -0
- package/dist/shims/fetch-cache.d.ts +3 -61
- package/dist/shims/fetch-cache.js +161 -108
- package/dist/shims/form.js +1 -1
- package/dist/shims/head.d.ts +10 -6
- package/dist/shims/head.js +15 -13
- package/dist/shims/headers.d.ts +13 -0
- package/dist/shims/headers.js +47 -4
- package/dist/shims/image.js +2 -1
- package/dist/shims/internal/app-page-props-cache-key.d.ts +5 -2
- package/dist/shims/internal/app-page-props-cache-key.js +24 -15
- package/dist/shims/internal/headers-state.d.ts +0 -1
- package/dist/shims/internal/work-store-scope.d.ts +5 -0
- package/dist/shims/internal/work-store-scope.js +24 -0
- package/dist/shims/metadata.js +3 -3
- package/dist/shims/navigation-errors.d.ts +6 -0
- package/dist/shims/navigation-errors.js +11 -1
- package/dist/shims/navigation.d.ts +7 -0
- package/dist/shims/navigation.js +45 -9
- package/dist/shims/request-context.d.ts +11 -0
- package/dist/shims/request-state-types.d.ts +2 -1
- package/dist/shims/router.js +12 -20
- package/dist/shims/server.d.ts +16 -0
- package/dist/shims/server.js +24 -4
- package/dist/shims/thenable-params.d.ts +4 -0
- package/dist/shims/thenable-params.js +25 -3
- package/dist/shims/unified-request-context.d.ts +1 -1
- package/dist/shims/unified-request-context.js +1 -0
- package/dist/shims/url-utils.d.ts +2 -0
- package/dist/shims/url-utils.js +3 -1
- package/dist/utils/client-runtime-metadata.js +1 -1
- package/dist/utils/hash.d.ts +7 -0
- package/dist/utils/hash.js +11 -1
- package/dist/utils/mdx-scan.d.ts +5 -0
- package/dist/utils/mdx-scan.js +8 -1
- package/dist/utils/package-name.d.ts +6 -0
- package/dist/utils/package-name.js +12 -1
- package/dist/utils/plugin-rsc-version.d.ts +4 -0
- package/dist/utils/plugin-rsc-version.js +15 -0
- package/dist/utils/prerender-output-paths.js +15 -4
- package/dist/utils/public-file-path.d.ts +10 -2
- package/dist/utils/public-file-path.js +13 -9
- package/dist/utils/public-routes.js +2 -2
- package/dist/utils/react-version.d.ts +3 -0
- package/dist/utils/react-version.js +1 -1
- package/dist/utils/regex-safety.d.ts +10 -0
- package/dist/utils/regex-safety.js +70 -18
- package/package.json +9 -5
package/dist/server/headers.js
CHANGED
|
@@ -48,7 +48,10 @@ const VINEXT_PRERENDER_READINESS_PATH = "/__vinext/prerender/readiness";
|
|
|
48
48
|
const VINEXT_PRERENDER_READINESS_HEADER = "X-Vinext-Prerender-Readiness";
|
|
49
49
|
/** TPR (Tailored Per-Request) revalidation interval in seconds. */
|
|
50
50
|
const VINEXT_REVALIDATE_HEADER = "x-vinext-revalidate";
|
|
51
|
-
/**
|
|
51
|
+
/**
|
|
52
|
+
* Actual Pages cache tag regenerated by an authenticated on-demand request.
|
|
53
|
+
* URI-encoded, because a decoded path can end in whitespace that Headers trims.
|
|
54
|
+
*/
|
|
52
55
|
const VINEXT_REVALIDATED_CACHE_TAG_HEADER = "x-vinext-revalidated-cache-tag";
|
|
53
56
|
/** Marker on cached ISR entries indicating RSC payload (value "1"). */
|
|
54
57
|
const VINEXT_RSC_MARKER_HEADER = "x-vinext-rsc";
|
|
@@ -58,6 +61,12 @@ const VINEXT_PARAMS_HEADER = "X-Vinext-Params";
|
|
|
58
61
|
const VINEXT_DYNAMIC_STALE_TIME_HEADER = "X-Vinext-Dynamic-Stale-Time";
|
|
59
62
|
/** Marks an RSC body carrying completion metadata after the Flight payload. */
|
|
60
63
|
const VINEXT_RSC_COMPLETION_METADATA_HEADER = "X-Vinext-Rsc-Completion-Metadata";
|
|
64
|
+
/**
|
|
65
|
+
* Carries the stored status of an App page RSC response whose 401, 403 or 404
|
|
66
|
+
* is its page's notFound(), forbidden() or unauthorized(). Middleware and
|
|
67
|
+
* config headers can't set it, and the request stage strips it.
|
|
68
|
+
*/
|
|
69
|
+
const VINEXT_SPECIAL_ERROR_STATUS_HEADER = "x-vinext-special-error-status";
|
|
61
70
|
/** URL-encoded rendered path and search after middleware/config rewrites. */
|
|
62
71
|
const VINEXT_RENDERED_PATH_AND_SEARCH_HEADER = "X-Vinext-Rendered-Path-And-Search";
|
|
63
72
|
/** Prerender-only JSON side channel carrying request cacheLife metadata. */
|
|
@@ -66,6 +75,14 @@ const VINEXT_PRERENDER_CACHE_LIFE_HEADER = "x-vinext-prerender-cache-life";
|
|
|
66
75
|
const VINEXT_PRERENDER_REWRITTEN_HEADER = "x-vinext-prerender-rewritten";
|
|
67
76
|
/** Marks a local prerender-server 500 that originated from a thrown render error. */
|
|
68
77
|
const VINEXT_PRERENDER_RENDER_ERROR_HEADER = "x-vinext-prerender-render-error";
|
|
78
|
+
/**
|
|
79
|
+
* Prerender-only marker: the response's 401, 403, 404 or redirect is its page's
|
|
80
|
+
* notFound(), forbidden(), unauthorized() or redirect(), which escaped the shell.
|
|
81
|
+
* Its value is the JSON of the headers to store: a redirect's own location, or
|
|
82
|
+
* `{}`. Only the prerender server sets it, from the special error the page
|
|
83
|
+
* recorded on its ctx, and it drops one that the response carries.
|
|
84
|
+
*/
|
|
85
|
+
const VINEXT_PRERENDER_SPECIAL_ERROR_HEADER = "x-vinext-prerender-special-error";
|
|
69
86
|
/** Internal marker persisted only inside metadata-route APP_ROUTE cache values. */
|
|
70
87
|
const VINEXT_METADATA_ROUTE_CACHE_HEADER = "x-vinext-metadata-route-cache";
|
|
71
88
|
/** Disabled-by-default client hint describing already-held App Router payload entries. */
|
|
@@ -175,4 +192,4 @@ const VINEXT_INTERNAL_HEADERS = [
|
|
|
175
192
|
VINEXT_TRACE_ROUTE_HEADER.toLowerCase()
|
|
176
193
|
];
|
|
177
194
|
//#endregion
|
|
178
|
-
export { ACTION_FORWARDED_HEADER, ACTION_REDIRECT_HEADER, ACTION_REDIRECT_STATUS_HEADER, ACTION_REDIRECT_TYPE_HEADER, ACTION_REVALIDATED_HEADER, FLIGHT_HEADERS, INTERNAL_HEADERS, MIDDLEWARE_HEADER_PREFIX, MIDDLEWARE_NEXT_HEADER, MIDDLEWARE_REWRITE_HEADER, MIDDLEWARE_SET_COOKIE_HEADER, MIDDLEWARE_SKIP_HEADER, NEXTJS_ACTION_NOT_FOUND_HEADER, NEXTJS_CACHE_HEADER, NEXTJS_DEPLOYMENT_ID_HEADER, NEXT_ACTION_HEADER, NEXT_CACHE_TAGS_HEADER, NEXT_HTML_REQUEST_ID_HEADER, NEXT_REQUEST_ID_HEADER, NEXT_ROUTER_PREFETCH_HEADER, NEXT_ROUTER_SEGMENT_PREFETCH_HEADER, NEXT_ROUTER_STALE_TIME_HEADER, NEXT_ROUTER_STATE_TREE_HEADER, NEXT_URL_HEADER, RSC_ACTION_HEADER, RSC_HEADER, VINEXT_CACHEABILITY_PROBE_HEADER, VINEXT_CACHEABILITY_PROBE_QUERY_PARAM, VINEXT_CACHEABILITY_PROBE_ROUTE_HEADER, VINEXT_CACHE_HEADER, VINEXT_CLIENT_REUSE_MANIFEST_HEADER, VINEXT_DYNAMIC_STALE_TIME_HEADER, VINEXT_EXPECTED_WORKER_VERSION_HEADER, VINEXT_INTERCEPTION_CONTEXT_HEADER, VINEXT_INTERCEPTION_ID_HEADER, VINEXT_INTERNAL_HEADERS, VINEXT_METADATA_ROUTE_CACHE_HEADER, VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_MW_CTX_HEADER, VINEXT_PARAMS_HEADER, VINEXT_PRERENDER_CACHE_LIFE_HEADER, VINEXT_PRERENDER_METADATA_ROUTES_PATH, VINEXT_PRERENDER_PAGES_STATIC_PATHS_PATH, VINEXT_PRERENDER_READINESS_HEADER, VINEXT_PRERENDER_READINESS_PATH, VINEXT_PRERENDER_RENDER_ERROR_HEADER, VINEXT_PRERENDER_REWRITTEN_HEADER, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER, VINEXT_PRERENDER_SPECULATIVE_HEADER, VINEXT_PRERENDER_STATIC_PARAMS_PATH, VINEXT_RENDERED_PATH_AND_SEARCH_HEADER, VINEXT_REVALIDATED_CACHE_TAG_HEADER, VINEXT_REVALIDATE_HEADER, VINEXT_REVALIDATE_HOST_HEADER, VINEXT_RSC_COMPLETION_METADATA_HEADER, VINEXT_RSC_MARKER_HEADER, VINEXT_RSC_REDIRECT_HEADER, VINEXT_RSC_REDIRECT_TYPE_HEADER, VINEXT_RSC_RENDER_MODE_HEADER, VINEXT_RSC_STATE_FINGERPRINT_HEADER, VINEXT_RSC_VARY_HEADER, VINEXT_STALE_TIME_PENDING_HEADER, VINEXT_TIMING_HEADER, VINEXT_TRACE_BUFFERED_BODY_HEADER, VINEXT_TRACE_ERROR_HEADER, VINEXT_TRACE_ROUTE_HEADER, isVinextRscVaryField };
|
|
195
|
+
export { ACTION_FORWARDED_HEADER, ACTION_REDIRECT_HEADER, ACTION_REDIRECT_STATUS_HEADER, ACTION_REDIRECT_TYPE_HEADER, ACTION_REVALIDATED_HEADER, FLIGHT_HEADERS, INTERNAL_HEADERS, MIDDLEWARE_HEADER_PREFIX, MIDDLEWARE_NEXT_HEADER, MIDDLEWARE_REWRITE_HEADER, MIDDLEWARE_SET_COOKIE_HEADER, MIDDLEWARE_SKIP_HEADER, NEXTJS_ACTION_NOT_FOUND_HEADER, NEXTJS_CACHE_HEADER, NEXTJS_DEPLOYMENT_ID_HEADER, NEXT_ACTION_HEADER, NEXT_CACHE_TAGS_HEADER, NEXT_HTML_REQUEST_ID_HEADER, NEXT_REQUEST_ID_HEADER, NEXT_ROUTER_PREFETCH_HEADER, NEXT_ROUTER_SEGMENT_PREFETCH_HEADER, NEXT_ROUTER_STALE_TIME_HEADER, NEXT_ROUTER_STATE_TREE_HEADER, NEXT_URL_HEADER, RSC_ACTION_HEADER, RSC_HEADER, VINEXT_CACHEABILITY_PROBE_HEADER, VINEXT_CACHEABILITY_PROBE_QUERY_PARAM, VINEXT_CACHEABILITY_PROBE_ROUTE_HEADER, VINEXT_CACHE_HEADER, VINEXT_CLIENT_REUSE_MANIFEST_HEADER, VINEXT_DYNAMIC_STALE_TIME_HEADER, VINEXT_EXPECTED_WORKER_VERSION_HEADER, VINEXT_INTERCEPTION_CONTEXT_HEADER, VINEXT_INTERCEPTION_ID_HEADER, VINEXT_INTERNAL_HEADERS, VINEXT_METADATA_ROUTE_CACHE_HEADER, VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_MW_CTX_HEADER, VINEXT_PARAMS_HEADER, VINEXT_PRERENDER_CACHE_LIFE_HEADER, VINEXT_PRERENDER_METADATA_ROUTES_PATH, VINEXT_PRERENDER_PAGES_STATIC_PATHS_PATH, VINEXT_PRERENDER_READINESS_HEADER, VINEXT_PRERENDER_READINESS_PATH, VINEXT_PRERENDER_RENDER_ERROR_HEADER, VINEXT_PRERENDER_REWRITTEN_HEADER, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER, VINEXT_PRERENDER_SPECIAL_ERROR_HEADER, VINEXT_PRERENDER_SPECULATIVE_HEADER, VINEXT_PRERENDER_STATIC_PARAMS_PATH, VINEXT_RENDERED_PATH_AND_SEARCH_HEADER, VINEXT_REVALIDATED_CACHE_TAG_HEADER, VINEXT_REVALIDATE_HEADER, VINEXT_REVALIDATE_HOST_HEADER, VINEXT_RSC_COMPLETION_METADATA_HEADER, VINEXT_RSC_MARKER_HEADER, VINEXT_RSC_REDIRECT_HEADER, VINEXT_RSC_REDIRECT_TYPE_HEADER, VINEXT_RSC_RENDER_MODE_HEADER, VINEXT_RSC_STATE_FINGERPRINT_HEADER, VINEXT_RSC_VARY_HEADER, VINEXT_SPECIAL_ERROR_STATUS_HEADER, VINEXT_STALE_TIME_PENDING_HEADER, VINEXT_TIMING_HEADER, VINEXT_TRACE_BUFFERED_BODY_HEADER, VINEXT_TRACE_ERROR_HEADER, VINEXT_TRACE_ROUTE_HEADER, isVinextRscVaryField };
|
|
@@ -6,6 +6,17 @@
|
|
|
6
6
|
* validator with the same opaque tag compare equal.
|
|
7
7
|
*/
|
|
8
8
|
export declare function matchesIfNoneMatch(ifNoneMatch: string | undefined, etag: string): boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Whether a page answers its request with a 304, as Next.js's
|
|
11
|
+
* `sendEtagResponse` does with `fresh(req.headers, { etag })`. Next.js gives a
|
|
12
|
+
* page no Last-Modified, so a request with If-Modified-Since gets the page, and
|
|
13
|
+
* a request `Cache-Control: no-cache` always does.
|
|
14
|
+
*/
|
|
15
|
+
export declare function isPageNotModified(request: {
|
|
16
|
+
cacheControl?: string;
|
|
17
|
+
ifModifiedSince?: string;
|
|
18
|
+
ifNoneMatch?: string;
|
|
19
|
+
}, etag: string): boolean;
|
|
9
20
|
/** Test an If-Match field using Next.js's weak/strong-equivalent comparison. */
|
|
10
21
|
export declare function matchesIfMatch(ifMatch: string | undefined, etag: string | undefined): boolean;
|
|
11
22
|
type StaticConditionalHeaders = {
|
|
@@ -31,6 +31,15 @@ function matchesIfNoneMatch(ifNoneMatch, etag) {
|
|
|
31
31
|
}
|
|
32
32
|
return sawTag && matched;
|
|
33
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* Whether a page answers its request with a 304, as Next.js's
|
|
36
|
+
* `sendEtagResponse` does with `fresh(req.headers, { etag })`. Next.js gives a
|
|
37
|
+
* page no Last-Modified, so a request with If-Modified-Since gets the page, and
|
|
38
|
+
* a request `Cache-Control: no-cache` always does.
|
|
39
|
+
*/
|
|
40
|
+
function isPageNotModified(request, etag) {
|
|
41
|
+
return !request.ifModifiedSince && !/(?:^|,)\s*no-cache\s*(?:,|$)/.test(request.cacheControl ?? "") && matchesIfNoneMatch(request.ifNoneMatch, etag);
|
|
42
|
+
}
|
|
34
43
|
/** Test an If-Match field using Next.js's weak/strong-equivalent comparison. */
|
|
35
44
|
function matchesIfMatch(ifMatch, etag) {
|
|
36
45
|
if (!ifMatch) return false;
|
|
@@ -114,4 +123,4 @@ function joinHeader(value) {
|
|
|
114
123
|
return Array.isArray(value) ? value.join(", ") : value;
|
|
115
124
|
}
|
|
116
125
|
//#endregion
|
|
117
|
-
export { evaluateStaticPreconditions, matchesIfMatch, matchesIfNoneMatch };
|
|
126
|
+
export { evaluateStaticPreconditions, isPageNotModified, matchesIfMatch, matchesIfNoneMatch };
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* `new Response(...)` boilerplate.
|
|
10
10
|
*
|
|
11
11
|
* Sites with route-specific bodies (e.g. `"404 - API route not found"`,
|
|
12
|
-
*
|
|
12
|
+
* generated worker templates) intentionally remain inline
|
|
13
13
|
* because their bodies are either tested-against fixtures or run inside template
|
|
14
14
|
* strings that have no access to runtime imports.
|
|
15
15
|
*
|
|
@@ -82,6 +82,44 @@ export type ParseImageParamsOptions = {
|
|
|
82
82
|
isDev?: boolean;
|
|
83
83
|
};
|
|
84
84
|
export declare function resolveDevImageRedirect(requestUrl: URL, allowedWidths?: number[], allowedQualities?: number[], options?: ParseImageParamsOptions): string | null;
|
|
85
|
+
export type ImageOptimizationSignal = {
|
|
86
|
+
/** Middleware response headers to send with the image. */
|
|
87
|
+
middlewareHeaders: Headers;
|
|
88
|
+
/** The request headers after middleware's overrides, when it set any. */
|
|
89
|
+
requestHeaders: Headers | null;
|
|
90
|
+
/** The image query after middleware and rewrites. */
|
|
91
|
+
search: string;
|
|
92
|
+
};
|
|
93
|
+
/**
|
|
94
|
+
* Mark the App Router's image endpoint response once the request has passed
|
|
95
|
+
* middleware and rewrites. A host that serves images itself (the Node
|
|
96
|
+
* production server) replaces the response with the image; other hosts send
|
|
97
|
+
* the response unchanged. The symbol carries the signal across the built RSC
|
|
98
|
+
* module boundary, so response headers cannot forge it.
|
|
99
|
+
*/
|
|
100
|
+
export declare function markImageOptimizationSignal(response: Response, signal: ImageOptimizationSignal): Response;
|
|
101
|
+
/** Return the signal of a framework-created image endpoint response. */
|
|
102
|
+
export declare function readImageOptimizationSignal(response: Response): ImageOptimizationSignal | null;
|
|
103
|
+
/**
|
|
104
|
+
* Carry a signal through the response-stage transport, which drops the
|
|
105
|
+
* symbol. The signal rides in the body of the bodiless carrier, with the
|
|
106
|
+
* carrier's status in the token-authenticated marker.
|
|
107
|
+
*/
|
|
108
|
+
export declare function serializeImageOptimizationSignalForTransport(response: Response, token: string): Response;
|
|
109
|
+
/** Restore and consume a signal returned by the trusted response-stage wrapper. */
|
|
110
|
+
export declare function restoreImageOptimizationSignalFromTransport(response: Response, token: string): Promise<Response>;
|
|
111
|
+
/**
|
|
112
|
+
* Whether a local source's pipeline status carries the file's bytes. A no-body
|
|
113
|
+
* success such as 204 serves no file, which Next.js rejects as an invalid
|
|
114
|
+
* image.
|
|
115
|
+
*/
|
|
116
|
+
export declare function isImageSourceBodyStatus(status: number): boolean;
|
|
117
|
+
/**
|
|
118
|
+
* Body Next.js answers, with a 400, for a local source that yields no image:
|
|
119
|
+
* a missing file, or anything middleware or routing answers in its place.
|
|
120
|
+
*/
|
|
121
|
+
export declare const INVALID_IMAGE_SOURCE_MESSAGE = "The requested resource isn't a valid image.";
|
|
122
|
+
export declare function invalidImageSourceResponse(): Response;
|
|
85
123
|
/**
|
|
86
124
|
* Parse and validate image optimization query parameters.
|
|
87
125
|
* Returns null if the request is malformed.
|
|
@@ -117,6 +155,22 @@ export declare const IMAGE_CONTENT_SECURITY_POLICY = "script-src 'none'; frame-s
|
|
|
117
155
|
* Returns false for SVG (unless dangerouslyAllowSVG is true), HTML, or any non-image type.
|
|
118
156
|
*/
|
|
119
157
|
export declare function isSafeImageContentType(contentType: string | null, dangerouslyAllowSVG?: boolean): boolean;
|
|
158
|
+
/**
|
|
159
|
+
* Cache state for a successful image response, sent as both `X-Nextjs-Cache`
|
|
160
|
+
* and `X-Vinext-Cache`.
|
|
161
|
+
*
|
|
162
|
+
* Next.js keeps optimized images in an image cache and labels each 200 with
|
|
163
|
+
* where the bytes came from: `MISS` when the optimizer ran for this request,
|
|
164
|
+
* `HIT` or `STALE` when the cache served them. vinext has no image cache on any
|
|
165
|
+
* runtime, so every successful response is transformed (or passed through) from
|
|
166
|
+
* the source for the request that receives it. Next.js behaves the same way
|
|
167
|
+
* when its image cache is disabled (`images.maximumDiskCacheSize: 0`): every
|
|
168
|
+
* 200 is a `MISS`. `HIT` and `STALE` need a cache of optimized images.
|
|
169
|
+
*
|
|
170
|
+
* Next.js sets the header after its ETag check, so a 304 and error responses
|
|
171
|
+
* go out without it. Only full image responses carry either header here too.
|
|
172
|
+
*/
|
|
173
|
+
export declare const IMAGE_RESPONSE_CACHE_STATE = "MISS";
|
|
120
174
|
/**
|
|
121
175
|
* Handlers for image optimization I/O operations.
|
|
122
176
|
* Workers provide these callbacks to adapt their specific bindings.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { badRequestResponse } from "./http-error-responses.js";
|
|
2
|
+
import { setCacheStateHeaders } from "./cache-headers.js";
|
|
2
3
|
//#region src/server/image-optimization.ts
|
|
3
4
|
/**
|
|
4
5
|
* Image optimization request handler.
|
|
@@ -77,6 +78,93 @@ function resolveDevImageRedirect(requestUrl, allowedWidths = [...DEFAULT_DEVICE_
|
|
|
77
78
|
if (resolved.origin !== requestUrl.origin) return null;
|
|
78
79
|
return resolved.pathname + resolved.search;
|
|
79
80
|
}
|
|
81
|
+
const IMAGE_OPTIMIZATION_SIGNAL = Symbol.for("vinext.image-optimization-signal");
|
|
82
|
+
/**
|
|
83
|
+
* Mark the App Router's image endpoint response once the request has passed
|
|
84
|
+
* middleware and rewrites. A host that serves images itself (the Node
|
|
85
|
+
* production server) replaces the response with the image; other hosts send
|
|
86
|
+
* the response unchanged. The symbol carries the signal across the built RSC
|
|
87
|
+
* module boundary, so response headers cannot forge it.
|
|
88
|
+
*/
|
|
89
|
+
function markImageOptimizationSignal(response, signal) {
|
|
90
|
+
Object.defineProperty(response, IMAGE_OPTIMIZATION_SIGNAL, { value: signal });
|
|
91
|
+
return response;
|
|
92
|
+
}
|
|
93
|
+
/** Return the signal of a framework-created image endpoint response. */
|
|
94
|
+
function readImageOptimizationSignal(response) {
|
|
95
|
+
const signal = Reflect.get(response, IMAGE_OPTIMIZATION_SIGNAL);
|
|
96
|
+
if (typeof signal !== "object" || signal === null) return null;
|
|
97
|
+
const { middlewareHeaders, requestHeaders, search } = signal;
|
|
98
|
+
return middlewareHeaders instanceof Headers && (requestHeaders === null || requestHeaders instanceof Headers) && typeof search === "string" ? {
|
|
99
|
+
middlewareHeaders,
|
|
100
|
+
requestHeaders,
|
|
101
|
+
search
|
|
102
|
+
} : null;
|
|
103
|
+
}
|
|
104
|
+
const IMAGE_OPTIMIZATION_SIGNAL_TRANSPORT_HEADER = "x-vinext-stage-image-optimization";
|
|
105
|
+
function isHeaderEntries(value) {
|
|
106
|
+
return Array.isArray(value) && value.every((entry) => Array.isArray(entry) && entry.length === 2 && typeof entry[0] === "string" && typeof entry[1] === "string");
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Carry a signal through the response-stage transport, which drops the
|
|
110
|
+
* symbol. The signal rides in the body of the bodiless carrier, with the
|
|
111
|
+
* carrier's status in the token-authenticated marker.
|
|
112
|
+
*/
|
|
113
|
+
function serializeImageOptimizationSignalForTransport(response, token) {
|
|
114
|
+
const signal = readImageOptimizationSignal(response);
|
|
115
|
+
if (signal === null) return response;
|
|
116
|
+
const headers = new Headers(response.headers);
|
|
117
|
+
headers.set(IMAGE_OPTIMIZATION_SIGNAL_TRANSPORT_HEADER, `${token}:${response.status}`);
|
|
118
|
+
return new Response(JSON.stringify({
|
|
119
|
+
middlewareHeaders: [...signal.middlewareHeaders],
|
|
120
|
+
requestHeaders: signal.requestHeaders ? [...signal.requestHeaders] : null,
|
|
121
|
+
search: signal.search
|
|
122
|
+
}), { headers });
|
|
123
|
+
}
|
|
124
|
+
/** Restore and consume a signal returned by the trusted response-stage wrapper. */
|
|
125
|
+
async function restoreImageOptimizationSignalFromTransport(response, token) {
|
|
126
|
+
const marker = response.headers.get(IMAGE_OPTIMIZATION_SIGNAL_TRANSPORT_HEADER);
|
|
127
|
+
if (marker === null || response.status < 200 || response.status > 599) return response;
|
|
128
|
+
const headers = new Headers(response.headers);
|
|
129
|
+
headers.delete(IMAGE_OPTIMIZATION_SIGNAL_TRANSPORT_HEADER);
|
|
130
|
+
const prefix = `${token}:`;
|
|
131
|
+
const status = marker.startsWith(prefix) ? Number(marker.slice(prefix.length)) : NaN;
|
|
132
|
+
if (!Number.isInteger(status) || status < 200 || status > 599) {
|
|
133
|
+
const body = response.status === 204 || response.status === 205 || response.status === 304 ? null : response.body;
|
|
134
|
+
return new Response(body, {
|
|
135
|
+
headers,
|
|
136
|
+
status: response.status,
|
|
137
|
+
statusText: response.statusText
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
const { middlewareHeaders, requestHeaders, search } = JSON.parse(await response.text()) ?? {};
|
|
141
|
+
if (!isHeaderEntries(middlewareHeaders) || requestHeaders !== null && !isHeaderEntries(requestHeaders) || typeof search !== "string") throw new Error("Invalid image optimization signal from the response stage");
|
|
142
|
+
return markImageOptimizationSignal(new Response(null, {
|
|
143
|
+
headers,
|
|
144
|
+
status
|
|
145
|
+
}), {
|
|
146
|
+
middlewareHeaders: new Headers(middlewareHeaders),
|
|
147
|
+
requestHeaders: requestHeaders ? new Headers(requestHeaders) : null,
|
|
148
|
+
search
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Whether a local source's pipeline status carries the file's bytes. A no-body
|
|
153
|
+
* success such as 204 serves no file, which Next.js rejects as an invalid
|
|
154
|
+
* image.
|
|
155
|
+
*/
|
|
156
|
+
function isImageSourceBodyStatus(status) {
|
|
157
|
+
return status >= 200 && status < 300 && status !== 204 && status !== 205;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Body Next.js answers, with a 400, for a local source that yields no image:
|
|
161
|
+
* a missing file, or anything middleware or routing answers in its place.
|
|
162
|
+
*/
|
|
163
|
+
const INVALID_IMAGE_SOURCE_MESSAGE = "The requested resource isn't a valid image.";
|
|
164
|
+
function invalidImageSourceResponse() {
|
|
165
|
+
return new Response(INVALID_IMAGE_SOURCE_MESSAGE, { status: 400 });
|
|
166
|
+
}
|
|
167
|
+
const RECURSIVE_IMAGE_URL_RE = /\/_(?:next|vinext)\/image(?:$|\/)/;
|
|
80
168
|
/**
|
|
81
169
|
* Parse and validate image optimization query parameters.
|
|
82
170
|
* Returns null if the request is malformed.
|
|
@@ -112,7 +200,9 @@ function parseImageParams(url, allowedWidths = [...DEFAULT_DEVICE_SIZES, ...DEFA
|
|
|
112
200
|
if (!normalizedUrl.startsWith("/") || normalizedUrl.startsWith("//")) return null;
|
|
113
201
|
try {
|
|
114
202
|
const base = "https://localhost";
|
|
115
|
-
|
|
203
|
+
const resolved = new URL(normalizedUrl, base);
|
|
204
|
+
if (resolved.origin !== base) return null;
|
|
205
|
+
if (RECURSIVE_IMAGE_URL_RE.test(decodeURIComponent(resolved.pathname))) return null;
|
|
116
206
|
} catch {
|
|
117
207
|
return null;
|
|
118
208
|
}
|
|
@@ -182,11 +272,32 @@ function setImageSecurityHeaders(headers, config) {
|
|
|
182
272
|
headers.set("X-Content-Type-Options", "nosniff");
|
|
183
273
|
headers.set("Content-Disposition", config?.contentDispositionType === "attachment" ? "attachment" : "inline");
|
|
184
274
|
}
|
|
185
|
-
|
|
186
|
-
|
|
275
|
+
/**
|
|
276
|
+
* Cache state for a successful image response, sent as both `X-Nextjs-Cache`
|
|
277
|
+
* and `X-Vinext-Cache`.
|
|
278
|
+
*
|
|
279
|
+
* Next.js keeps optimized images in an image cache and labels each 200 with
|
|
280
|
+
* where the bytes came from: `MISS` when the optimizer ran for this request,
|
|
281
|
+
* `HIT` or `STALE` when the cache served them. vinext has no image cache on any
|
|
282
|
+
* runtime, so every successful response is transformed (or passed through) from
|
|
283
|
+
* the source for the request that receives it. Next.js behaves the same way
|
|
284
|
+
* when its image cache is disabled (`images.maximumDiskCacheSize: 0`): every
|
|
285
|
+
* 200 is a `MISS`. `HIT` and `STALE` need a cache of optimized images.
|
|
286
|
+
*
|
|
287
|
+
* Next.js sets the header after its ETag check, so a 304 and error responses
|
|
288
|
+
* go out without it. Only full image responses carry either header here too.
|
|
289
|
+
*/
|
|
290
|
+
const IMAGE_RESPONSE_CACHE_STATE = "MISS";
|
|
291
|
+
/** Headers shared by every successful image response, transformed or not. */
|
|
292
|
+
function setImageResponseHeaders(headers, config) {
|
|
187
293
|
headers.set("Cache-Control", IMAGE_CACHE_CONTROL);
|
|
188
294
|
headers.set("Vary", "Accept");
|
|
189
295
|
setImageSecurityHeaders(headers, config);
|
|
296
|
+
setCacheStateHeaders(headers, IMAGE_RESPONSE_CACHE_STATE);
|
|
297
|
+
}
|
|
298
|
+
function createPassthroughImageResponse(source, config) {
|
|
299
|
+
const headers = new Headers(source.headers);
|
|
300
|
+
setImageResponseHeaders(headers, config);
|
|
190
301
|
return new Response(source.body, {
|
|
191
302
|
status: 200,
|
|
192
303
|
headers
|
|
@@ -204,7 +315,7 @@ async function handleImageOptimization(request, handlers, allowedWidths, imageCo
|
|
|
204
315
|
if (!params) return badRequestResponse();
|
|
205
316
|
const { imageUrl, width, quality } = params;
|
|
206
317
|
const source = await handlers.fetchAsset(imageUrl, request);
|
|
207
|
-
if (!source.ok || !source.body) return
|
|
318
|
+
if (!source.ok || !source.body) return invalidImageSourceResponse();
|
|
208
319
|
const format = negotiateImageFormat(request.headers.get("Accept"));
|
|
209
320
|
const sourceContentType = source.headers.get("Content-Type");
|
|
210
321
|
if (!isSafeImageContentType(sourceContentType, imageConfig?.dangerouslyAllowSVG)) return new Response("The requested resource is not an allowed image type", { status: 400 });
|
|
@@ -216,9 +327,7 @@ async function handleImageOptimization(request, handlers, allowedWidths, imageCo
|
|
|
216
327
|
quality
|
|
217
328
|
});
|
|
218
329
|
const headers = new Headers(transformed.headers);
|
|
219
|
-
headers
|
|
220
|
-
headers.set("Vary", "Accept");
|
|
221
|
-
setImageSecurityHeaders(headers, imageConfig);
|
|
330
|
+
setImageResponseHeaders(headers, imageConfig);
|
|
222
331
|
if (!isSafeImageContentType(headers.get("Content-Type"), imageConfig?.dangerouslyAllowSVG)) headers.set("Content-Type", format);
|
|
223
332
|
return new Response(transformed.body, {
|
|
224
333
|
status: 200,
|
|
@@ -232,7 +341,7 @@ async function handleImageOptimization(request, handlers, allowedWidths, imageCo
|
|
|
232
341
|
} catch (e) {
|
|
233
342
|
console.error("[vinext] Image fallback error, refetching source image:", e);
|
|
234
343
|
const refetchedSource = await handlers.fetchAsset(imageUrl, request);
|
|
235
|
-
if (!refetchedSource.ok || !refetchedSource.body) return
|
|
344
|
+
if (!refetchedSource.ok || !refetchedSource.body) return invalidImageSourceResponse();
|
|
236
345
|
if (!isSafeImageContentType(refetchedSource.headers.get("Content-Type"), imageConfig?.dangerouslyAllowSVG)) return new Response("The requested resource is not an allowed image type", { status: 400 });
|
|
237
346
|
return createPassthroughImageResponse(refetchedSource, imageConfig);
|
|
238
347
|
}
|
|
@@ -287,4 +396,4 @@ function handleConfiguredImageOptimization(request, fetchAsset, allowedWidths, i
|
|
|
287
396
|
}, allowedWidths, imageConfig);
|
|
288
397
|
}
|
|
289
398
|
//#endregion
|
|
290
|
-
export { DEFAULT_DEVICE_SIZES, DEFAULT_IMAGE_SIZES, IMAGE_CACHE_CONTROL, IMAGE_CONTENT_SECURITY_POLICY, IMAGE_OPTIMIZATION_PATH, VINEXT_IMAGE_OPTIMIZATION_PATH, getImageOptimizer, handleConfiguredImageOptimization, handleImageOptimization, isImageOptimizationPath, isSafeImageContentType, negotiateImageFormat, parseImageParams, resolveDevImageRedirect, setImageOptimizer };
|
|
399
|
+
export { DEFAULT_DEVICE_SIZES, DEFAULT_IMAGE_SIZES, IMAGE_CACHE_CONTROL, IMAGE_CONTENT_SECURITY_POLICY, IMAGE_OPTIMIZATION_PATH, IMAGE_RESPONSE_CACHE_STATE, INVALID_IMAGE_SOURCE_MESSAGE, VINEXT_IMAGE_OPTIMIZATION_PATH, getImageOptimizer, handleConfiguredImageOptimization, handleImageOptimization, invalidImageSourceResponse, isImageOptimizationPath, isImageSourceBodyStatus, isSafeImageContentType, markImageOptimizationSignal, negotiateImageFormat, parseImageParams, readImageOptimizationSignal, resolveDevImageRedirect, restoreImageOptimizationSignalFromTransport, serializeImageOptimizationSignalForTransport, setImageOptimizer };
|
|
@@ -112,7 +112,17 @@ export declare function pagesIsrCacheKey(pathname: string, buildId?: string, i18
|
|
|
112
112
|
* Cloudflare KV key under its 512-byte limit for long pathnames.
|
|
113
113
|
*/
|
|
114
114
|
export declare function appIsrCacheKey(pathname: string, suffix: string, buildId?: string | undefined): string;
|
|
115
|
+
/**
|
|
116
|
+
* Compute the ISR key for a PPR fallback shell artifact, such as the HTML for
|
|
117
|
+
* `/en/[slug]`. Shells get their own namespace: a request for the literal path
|
|
118
|
+
* `/en/%5Bslug%5D` decodes to the same pathname, and its render must not be
|
|
119
|
+
* stored where every unknown `[slug]` reads its shell. The namespace is a
|
|
120
|
+
* prefix of its own rather than a part after the build ID, which can contain
|
|
121
|
+
* `:` and so could spell it.
|
|
122
|
+
*/
|
|
123
|
+
export declare function appIsrFallbackShellKey(pathname: string, suffix: "html" | "rsc", buildId?: string | undefined): string;
|
|
115
124
|
export declare function appIsrHtmlKey(pathname: string): string;
|
|
125
|
+
export declare function appIsrFallbackShellHtmlKey(pathname: string): string;
|
|
116
126
|
/**
|
|
117
127
|
* Build the ISR cache key for an RSC payload.
|
|
118
128
|
*
|
package/dist/server/isr-cache.js
CHANGED
|
@@ -1,15 +1,29 @@
|
|
|
1
1
|
import { PRERENDER_REVALIDATE_HEADER, PRERENDER_REVALIDATE_ONLY_GENERATED_HEADER } from "../utils/protocol-headers.js";
|
|
2
2
|
import { normalizePathnameForRouteMatch } from "../routing/utils.js";
|
|
3
3
|
import { getRequestExecutionContext } from "../shims/request-context.js";
|
|
4
|
+
import { isInterceptionMatchedUrlPath } from "./normalize-path.js";
|
|
4
5
|
import { reportRequestError } from "./instrumentation.js";
|
|
5
6
|
import { getCdnCacheAdapter } from "../shims/cdn-cache.js";
|
|
6
|
-
import { fnv1a64 } from "../utils/hash.js";
|
|
7
7
|
import { normalizeMountedSlotsHeader } from "./app-mounted-slots-header.js";
|
|
8
8
|
import { APP_RSC_RENDER_MODE_NAVIGATION, getRscRenderModeCacheVariant } from "./app-rsc-render-mode.js";
|
|
9
|
-
import { normalizeAppPageInterceptionProofPathname } from "./app-page-render-identity.js";
|
|
10
9
|
import { getRevalidateSecret, isOnDemandRevalidateRequest, isRevalidateSecret } from "./revalidation-request.js";
|
|
10
|
+
import { createHash } from "node:crypto";
|
|
11
11
|
//#region src/server/isr-cache.ts
|
|
12
12
|
/**
|
|
13
|
+
* ISR (Incremental Static Regeneration) cache layer.
|
|
14
|
+
*
|
|
15
|
+
* Wraps the pluggable CacheHandler with stale-while-revalidate semantics:
|
|
16
|
+
* - Fresh hit: serve immediately
|
|
17
|
+
* - Stale hit: serve immediately + trigger background regeneration
|
|
18
|
+
* - Miss: render synchronously, cache, serve
|
|
19
|
+
*
|
|
20
|
+
* Background regeneration is deduped — only one regeneration per cache key
|
|
21
|
+
* runs at a time, preventing thundering herd on popular pages.
|
|
22
|
+
*
|
|
23
|
+
* This layer works with any CacheHandler backend (memory, Redis, KV, etc.)
|
|
24
|
+
* because it only uses the standard get/set interface.
|
|
25
|
+
*/
|
|
26
|
+
/**
|
|
13
27
|
* Get a cache entry with staleness information.
|
|
14
28
|
*
|
|
15
29
|
* Returns { value, isStale: false } for fresh entries,
|
|
@@ -151,12 +165,19 @@ function buildAppPageCacheValue(html, rscData, status, renderObservation, header
|
|
|
151
165
|
function normalizeCachePathname(pathname) {
|
|
152
166
|
return pathname === "/" ? "/" : pathname.replace(/\/$/, "");
|
|
153
167
|
}
|
|
168
|
+
/**
|
|
169
|
+
* Digest a request-controlled key part. It must be collision resistant: a
|
|
170
|
+
* crafted value that shared a weaker hash with another would share its entry.
|
|
171
|
+
*/
|
|
172
|
+
function digestKeyPart(value) {
|
|
173
|
+
return createHash("sha256").update(value).digest("hex");
|
|
174
|
+
}
|
|
154
175
|
function buildCacheKey(prefix, pathname, suffix) {
|
|
155
176
|
const normalized = normalizeCachePathname(pathname);
|
|
156
177
|
const suffixPart = suffix ? `:${suffix}` : "";
|
|
157
178
|
const key = `${prefix}:${normalized}${suffixPart}`;
|
|
158
179
|
if (key.length <= 200) return key;
|
|
159
|
-
return `${prefix}:__hash:${
|
|
180
|
+
return `${prefix}:__hash:${digestKeyPart(normalized)}${suffixPart}`;
|
|
160
181
|
}
|
|
161
182
|
/**
|
|
162
183
|
* Compute an ISR cache key for a given router type and pathname.
|
|
@@ -179,11 +200,25 @@ function pagesIsrCacheKey(pathname, buildId, i18nCacheVariant) {
|
|
|
179
200
|
function appIsrCacheKey(pathname, suffix, buildId = process.env.__VINEXT_BUILD_ID) {
|
|
180
201
|
return buildCacheKey(buildId ? `app:v2:${buildId}` : "app:v2", pathname, suffix);
|
|
181
202
|
}
|
|
203
|
+
/**
|
|
204
|
+
* Compute the ISR key for a PPR fallback shell artifact, such as the HTML for
|
|
205
|
+
* `/en/[slug]`. Shells get their own namespace: a request for the literal path
|
|
206
|
+
* `/en/%5Bslug%5D` decodes to the same pathname, and its render must not be
|
|
207
|
+
* stored where every unknown `[slug]` reads its shell. The namespace is a
|
|
208
|
+
* prefix of its own rather than a part after the build ID, which can contain
|
|
209
|
+
* `:` and so could spell it.
|
|
210
|
+
*/
|
|
211
|
+
function appIsrFallbackShellKey(pathname, suffix, buildId = process.env.__VINEXT_BUILD_ID) {
|
|
212
|
+
return buildCacheKey(buildId ? `app-fallback-shell:v1:${buildId}` : "app-fallback-shell:v1", pathname, suffix);
|
|
213
|
+
}
|
|
182
214
|
function appIsrHtmlKey(pathname) {
|
|
183
215
|
return appIsrCacheKey(pathname, "html");
|
|
184
216
|
}
|
|
217
|
+
function appIsrFallbackShellHtmlKey(pathname) {
|
|
218
|
+
return appIsrFallbackShellKey(pathname, "html");
|
|
219
|
+
}
|
|
185
220
|
function normalizeInterceptionContextForCacheKey(interceptionContext) {
|
|
186
|
-
return
|
|
221
|
+
return isInterceptionMatchedUrlPath(interceptionContext) ? interceptionContext : null;
|
|
187
222
|
}
|
|
188
223
|
/**
|
|
189
224
|
* Build the ISR cache key for an RSC payload.
|
|
@@ -200,9 +235,9 @@ function appIsrRscKey(pathname, mountedSlotsHeader, renderMode = APP_RSC_RENDER_
|
|
|
200
235
|
const normalizedMountedSlotsHeader = normalizeMountedSlotsHeader(mountedSlotsHeader);
|
|
201
236
|
const sourceVariant = interceptionContext === void 0 || interceptionContext === null ? null : normalizeInterceptionContextForCacheKey(interceptionContext);
|
|
202
237
|
const variant = [
|
|
203
|
-
sourceVariant ? `source:${
|
|
204
|
-
interceptionId ? `selector:${
|
|
205
|
-
normalizedMountedSlotsHeader ? `slots:${
|
|
238
|
+
sourceVariant ? `source:${digestKeyPart(sourceVariant)}` : null,
|
|
239
|
+
interceptionId ? `selector:${digestKeyPart(interceptionId)}` : null,
|
|
240
|
+
normalizedMountedSlotsHeader ? `slots:${digestKeyPart(normalizedMountedSlotsHeader)}` : null,
|
|
206
241
|
getRscRenderModeCacheVariant(renderMode)
|
|
207
242
|
].filter((part) => part !== null).join(":");
|
|
208
243
|
return appIsrCacheKey(pathname, variant ? `rsc:${variant}` : "rsc");
|
|
@@ -211,4 +246,4 @@ function appIsrRouteKey(pathname) {
|
|
|
211
246
|
return appIsrCacheKey(pathname, pathname !== "/" && pathname.endsWith("/") ? "route:trailing-slash" : "route");
|
|
212
247
|
}
|
|
213
248
|
//#endregion
|
|
214
|
-
export { PRERENDER_REVALIDATE_HEADER, PRERENDER_REVALIDATE_ONLY_GENERATED_HEADER, appIsrCacheKey, appIsrHtmlKey, appIsrRouteKey, appIsrRscKey, buildAppPageCacheValue, buildPagesCacheValue, coalesceOnDemandRevalidation, getRevalidateSecret, isOnDemandRevalidateRequest, isRevalidateSecret, isrCacheControl, isrCacheKey, isrGet, isrSet, isrSetPrerenderedAppPage, normalizeMountedSlotsHeader, pagesIsrCacheKey, resolveRouteExpireSeconds, triggerBackgroundRegeneration };
|
|
249
|
+
export { PRERENDER_REVALIDATE_HEADER, PRERENDER_REVALIDATE_ONLY_GENERATED_HEADER, appIsrCacheKey, appIsrFallbackShellHtmlKey, appIsrFallbackShellKey, appIsrHtmlKey, appIsrRouteKey, appIsrRscKey, buildAppPageCacheValue, buildPagesCacheValue, coalesceOnDemandRevalidation, getRevalidateSecret, isOnDemandRevalidateRequest, isRevalidateSecret, isrCacheControl, isrCacheKey, isrGet, isrSet, isrSetPrerenderedAppPage, normalizeMountedSlotsHeader, pagesIsrCacheKey, resolveRouteExpireSeconds, triggerBackgroundRegeneration };
|
|
@@ -3,6 +3,7 @@ import { closeAfterResponse, createRequestContext, runWithRequestContext } from
|
|
|
3
3
|
import { decodeMatchedParams } from "../routing/utils.js";
|
|
4
4
|
import { getRequestExecutionContext } from "../shims/request-context.js";
|
|
5
5
|
import { VINEXT_METADATA_ROUTE_CACHE_HEADER } from "./headers.js";
|
|
6
|
+
import { runInWorkStoreScope } from "../shims/internal/work-store-scope.js";
|
|
6
7
|
import { notFoundResponse } from "./http-error-responses.js";
|
|
7
8
|
import { beginRouteCacheability, markRouteCacheabilityExplicitResponsePolicy, markRouteCacheabilityResponseBodyComplete, recordRouteCacheability } from "../shims/cacheability-classification.js";
|
|
8
9
|
import { NEVER_CACHE_CONTROL, applyCdnResponseHeaders, hasCdnResponsePolicy } from "./cache-control.js";
|
|
@@ -215,7 +216,7 @@ async function writeRenderedMetadataRoute(options, route, routeKey, rendered, pr
|
|
|
215
216
|
async function runMetadataRouteRegeneration(options, route, render, routeKey, previousEntry, executionContext) {
|
|
216
217
|
const requestContext = createRequestContext({ executionContext });
|
|
217
218
|
try {
|
|
218
|
-
await runWithRequestContext(requestContext, async () => {
|
|
219
|
+
await runWithRequestContext(requestContext, () => runInWorkStoreScope(async () => {
|
|
219
220
|
ensureFetchPatch();
|
|
220
221
|
beginMetadataRouteCacheability(route);
|
|
221
222
|
setCurrentFetchSoftTags(buildMetadataRouteTags(route, options.cleanPathname, []));
|
|
@@ -225,7 +226,7 @@ async function runMetadataRouteRegeneration(options, route, render, routeKey, pr
|
|
|
225
226
|
} finally {
|
|
226
227
|
rendered.response.body?.cancel().catch(() => {});
|
|
227
228
|
}
|
|
228
|
-
});
|
|
229
|
+
}));
|
|
229
230
|
} finally {
|
|
230
231
|
await closeAfterResponse(requestContext);
|
|
231
232
|
}
|
|
@@ -512,6 +513,12 @@ async function handleMetadataRouteRequest(options) {
|
|
|
512
513
|
decodeMatchedParams(runtimeParams);
|
|
513
514
|
match.params = runtimeParams;
|
|
514
515
|
}
|
|
516
|
+
const render = async () => {
|
|
517
|
+
setCurrentFetchSoftTags(buildMetadataRouteTags(route, options.cleanPathname, []));
|
|
518
|
+
return captureRenderedMetadataRoute(route.isDynamic ? await callDynamicMetadataRoute(route, match, options.makeThenableParams, functions) : serveStaticMetadataRoute(route), route, options.cleanPathname);
|
|
519
|
+
};
|
|
520
|
+
const cached = await readMatchedPrerenderedMetadataRouteResponse(options, route, render);
|
|
521
|
+
if (cached.response) return cached.response;
|
|
515
522
|
if (route.isDynamic && isImageMetadataRoute(route) && functions.dynamicParams === false) {
|
|
516
523
|
const validationParams = { ...rawParams };
|
|
517
524
|
canonicalizeAppPageParams(validationParams);
|
|
@@ -526,12 +533,6 @@ async function handleMetadataRouteRequest(options) {
|
|
|
526
533
|
});
|
|
527
534
|
if (dynamicParamsResponse) return dynamicParamsResponse;
|
|
528
535
|
}
|
|
529
|
-
const render = async () => {
|
|
530
|
-
setCurrentFetchSoftTags(buildMetadataRouteTags(route, options.cleanPathname, []));
|
|
531
|
-
return captureRenderedMetadataRoute(route.isDynamic ? await callDynamicMetadataRoute(route, match, options.makeThenableParams, functions) : serveStaticMetadataRoute(route), route, options.cleanPathname);
|
|
532
|
-
};
|
|
533
|
-
const cached = await readMatchedPrerenderedMetadataRouteResponse(options, route, render);
|
|
534
|
-
if (cached.response) return cached.response;
|
|
535
536
|
const rendered = await render();
|
|
536
537
|
await writeMetadataRouteMiss(options, route, rendered, cached.cachedEntry);
|
|
537
538
|
return rendered.response;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { analyzeRegexSafety, regexAtomsMayOverlap } from "../utils/regex-safety.js";
|
|
1
|
+
import { analyzeRegexSafety, mayHaveNamedGroups, regexAtomsMayOverlap } from "../utils/regex-safety.js";
|
|
2
2
|
import { middlewarePathTokensToRegExp, normalizeMiddlewarePathTokens, parseMiddlewarePath } from "./middleware-path-to-regexp.js";
|
|
3
3
|
//#region src/server/middleware-matcher-pattern.ts
|
|
4
4
|
const MATCHER_OBJECT_KEYS = /* @__PURE__ */ new Set([
|
|
@@ -138,8 +138,11 @@ function hasOverlappingSequentialRepetition(pattern) {
|
|
|
138
138
|
}
|
|
139
139
|
return false;
|
|
140
140
|
}
|
|
141
|
-
function unsafeTokenReason(token) {
|
|
142
|
-
const regexSafetyIssue = analyzeRegexSafety(token.pattern, {
|
|
141
|
+
function unsafeTokenReason(token, namedGroups) {
|
|
142
|
+
const regexSafetyIssue = analyzeRegexSafety(token.pattern, {
|
|
143
|
+
ignoreCase: true,
|
|
144
|
+
namedGroups
|
|
145
|
+
});
|
|
143
146
|
if (regexSafetyIssue) {
|
|
144
147
|
if (regexSafetyIssue === "analysis budget exceeded") return `parameter "${token.name}" exceeds the regex analysis budget`;
|
|
145
148
|
return `parameter "${token.name}" contains ${regexSafetyIssue}`;
|
|
@@ -150,9 +153,10 @@ function unsafeTokenReason(token) {
|
|
|
150
153
|
return null;
|
|
151
154
|
}
|
|
152
155
|
function validateTokens(tokens) {
|
|
156
|
+
const namedGroups = tokens.some((token) => typeof token !== "string" && mayHaveNamedGroups(token.pattern));
|
|
153
157
|
for (const token of tokens) {
|
|
154
158
|
if (typeof token === "string") continue;
|
|
155
|
-
const reason = unsafeTokenReason(token);
|
|
159
|
+
const reason = unsafeTokenReason(token, namedGroups);
|
|
156
160
|
if (reason) return reason;
|
|
157
161
|
}
|
|
158
162
|
return null;
|
|
@@ -7,6 +7,8 @@ export type MiddlewareLocaleMatchContext = {
|
|
|
7
7
|
defaultLocale: string;
|
|
8
8
|
} | {
|
|
9
9
|
kind: "internal" | "literal";
|
|
10
|
+
} | {
|
|
11
|
+
kind: "next-data";
|
|
10
12
|
};
|
|
11
13
|
export declare function matchesMiddleware(pathname: string, matcher: MatcherConfig | undefined, request?: Request, i18nConfig?: NextI18nConfig | null, localeContext?: MiddlewareLocaleMatchContext): boolean;
|
|
12
14
|
/**
|
|
@@ -49,6 +49,7 @@ function matchesMiddlewarePathname(pathname, matcher, i18nConfig, localeContext)
|
|
|
49
49
|
return false;
|
|
50
50
|
}
|
|
51
51
|
function matchMatcherPattern(pathname, pattern, i18nConfig, localeContext) {
|
|
52
|
+
if (localeContext?.kind === "next-data") return matchNextDataPattern(pathname, pattern, i18nConfig, true);
|
|
52
53
|
if (!i18nConfig) return matchPattern(pathname, pattern);
|
|
53
54
|
if (localeContext) {
|
|
54
55
|
if (localeContext.kind === "internal") return false;
|
|
@@ -57,9 +58,25 @@ function matchMatcherPattern(pathname, pattern, i18nConfig, localeContext) {
|
|
|
57
58
|
return matchPattern(stripLocalePrefix(pathname, i18nConfig) ?? pathname, pattern);
|
|
58
59
|
}
|
|
59
60
|
function matchObjectMatcher(pathname, matcher, i18nConfig, localeContext) {
|
|
61
|
+
if (localeContext?.kind === "next-data") return matchNextDataPattern(pathname, matcher.source, i18nConfig, matcher.locale !== false);
|
|
60
62
|
if (matcher.locale !== false) return matchMatcherPattern(pathname, matcher.source, i18nConfig, localeContext);
|
|
61
63
|
return matchPattern(localeContext?.kind === "defaulted" ? `/${localeContext.defaultLocale}${pathname === "/" ? "" : pathname}` : pathname, matcher.source);
|
|
62
64
|
}
|
|
65
|
+
function matchNextDataPattern(pathname, source, i18nConfig, localized) {
|
|
66
|
+
if (compiledPattern(source) === UNSAFE_MATCHER_PATTERN) return true;
|
|
67
|
+
return matchPattern(pathname, nextDataMatcherSource(source, i18nConfig, localized));
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* The source Next.js compiles for a matcher: an optional `_next/data/<buildId>`
|
|
71
|
+
* prefix, an internal locale segment under i18n, and an optional data suffix.
|
|
72
|
+
* Next.js also accepts App Router transport suffixes, which end in `.rsc` and
|
|
73
|
+
* so can never match a `.json` data URL.
|
|
74
|
+
* https://github.com/vercel/next.js/blob/v16.2.7/packages/next/src/build/analysis/get-page-static-info.ts
|
|
75
|
+
*/
|
|
76
|
+
function nextDataMatcherSource(source, i18nConfig, localized) {
|
|
77
|
+
const isRoot = source === "/";
|
|
78
|
+
return `/:nextData(_next/data/[^/]{1,})?${i18nConfig && localized ? `/:nextInternalLocale((?!_next/)[^/.]{1,})${isRoot ? "" : source}` : source}${isRoot ? `(${i18nConfig ? "|\\.json|" : ""}/?index|/?index\\.json)?` : "{(\\.json)}?"}`;
|
|
79
|
+
}
|
|
63
80
|
function stripLocalePrefix(pathname, i18nConfig) {
|
|
64
81
|
if (pathname === "/") return null;
|
|
65
82
|
const lowerFirstSegment = pathname.split("/")[1]?.toLowerCase();
|
|
@@ -71,13 +88,17 @@ function stripFirstPathSegment(pathname) {
|
|
|
71
88
|
}
|
|
72
89
|
function matchPattern(pathname, pattern) {
|
|
73
90
|
if (pattern === "/" && (pathname === "//" || pathname === "/?" || pathname === "/#")) return false;
|
|
91
|
+
const compiled = compiledPattern(pattern);
|
|
92
|
+
if (compiled === UNSAFE_MATCHER_PATTERN) return true;
|
|
93
|
+
return compiled.test(pathname);
|
|
94
|
+
}
|
|
95
|
+
function compiledPattern(pattern) {
|
|
74
96
|
let cached = _mwPatternCache.get(pattern);
|
|
75
97
|
if (cached === void 0) {
|
|
76
98
|
cached = compileMatcherPattern(pattern);
|
|
77
99
|
_mwPatternCache.set(pattern, cached);
|
|
78
100
|
}
|
|
79
|
-
|
|
80
|
-
return cached.test(pathname);
|
|
101
|
+
return cached;
|
|
81
102
|
}
|
|
82
103
|
function compileMatcherPattern(pattern) {
|
|
83
104
|
const result = compileMiddlewareMatcherPattern(pattern);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import "./headers.js";
|
|
1
2
|
//#region src/server/middleware-response-headers.ts
|
|
2
3
|
const ADDITIVE_RESPONSE_HEADER_NAMES = /* @__PURE__ */ new Set(["set-cookie", "vary"]);
|
|
3
4
|
function mergeVaryHeader(target, value) {
|
|
@@ -28,6 +29,7 @@ function mergeMiddlewareResponseHeaders(target, middlewareHeaders) {
|
|
|
28
29
|
if (!middlewareHeaders) return;
|
|
29
30
|
for (const [key, value] of middlewareHeaders) {
|
|
30
31
|
const lowerName = key.toLowerCase();
|
|
32
|
+
if (lowerName === "x-vinext-special-error-status") continue;
|
|
31
33
|
if (lowerName === "link" && !value) continue;
|
|
32
34
|
if (lowerName === "vary") {
|
|
33
35
|
mergeVaryHeader(target, value);
|