vinext 1.3.1 → 1.4.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 +25 -22
- package/THIRD_PARTY_LICENSES.md +47 -0
- package/dist/_virtual/_rolldown/runtime.js +3 -2
- package/dist/build/prerender.js +4 -3
- package/dist/build/report.d.ts +0 -14
- package/dist/build/report.js +1 -51
- package/dist/check.js +4 -7
- package/dist/cli.js +3 -0
- package/dist/client/dev-error-overlay-store.d.ts +1 -0
- package/dist/client/dev-error-overlay.d.ts +2 -0
- package/dist/client/dev-error-overlay.js +20 -4
- package/dist/client/navigation-runtime.d.ts +13 -1
- package/dist/client/navigation-runtime.js +1 -1
- package/dist/config/config-matchers.js +2 -0
- package/dist/config/destination-params.d.ts +2 -1
- package/dist/config/destination-params.js +52 -2
- package/dist/config/next-config.d.ts +25 -0
- package/dist/config/next-config.js +82 -4
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/dbcs-codec.js +327 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/dbcs-data.js +123 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/index.js +29 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/internal.js +134 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/sbcs-codec.js +50 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/sbcs-data-generated.js +455 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/sbcs-data.js +147 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/big5-added.json.js +169 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/cp936.json.js +2584 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/cp949.json.js +2220 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/cp950.json.js +227 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/eucjp.json.js +425 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/gb18030-ranges.json.js +427 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/gbk-added.json.js +229 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/shiftjis.json.js +292 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/utf16.js +106 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/utf7.js +182 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/bom-handling.js +42 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/extend-node.js +147 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/index.js +94 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/streams.js +95 -0
- package/dist/deps/.pnpm/safer-buffer@2.1.2/deps/safer-buffer/safer.js +45 -0
- package/dist/entries/app-rsc-entry.js +17 -49
- package/dist/entries/app-rsc-manifest.js +3 -4
- package/dist/entries/app-ssr-entry.js +1 -0
- package/dist/entries/pages-server-entry.js +36 -9
- package/dist/index.js +112 -90
- package/dist/init-cloudflare.d.ts +1 -3
- package/dist/init-cloudflare.js +10 -48
- package/dist/init-platform.d.ts +2 -0
- package/dist/init-platform.js +4 -0
- package/dist/plugins/extensionless-dynamic-import.js +6 -2
- package/dist/plugins/next-intl-catalog.d.ts +12 -0
- package/dist/plugins/next-intl-catalog.js +85 -0
- package/dist/plugins/pages-node-externals.d.ts +1 -0
- package/dist/plugins/pages-node-externals.js +1 -1
- package/dist/plugins/strip-server-exports.js +2 -1
- package/dist/plugins/use-cache-callable.d.ts +1 -1
- package/dist/plugins/use-cache-callable.js +136 -94
- package/dist/routing/app-route-graph.d.ts +6 -0
- package/dist/routing/app-route-graph.js +9 -1
- package/dist/server/api-handler.js +21 -5
- package/dist/server/app-bfcache-identity.js +1 -1
- package/dist/server/app-browser-entry.js +86 -66
- package/dist/server/app-browser-history-controller.d.ts +5 -4
- package/dist/server/app-browser-history-controller.js +93 -15
- package/dist/server/app-browser-navigation-controller.d.ts +2 -2
- package/dist/server/app-browser-navigation-controller.js +1 -2
- package/dist/server/app-browser-rsc-redirect.js +7 -7
- package/dist/server/app-browser-server-action-client.d.ts +2 -0
- package/dist/server/app-browser-server-action-client.js +5 -4
- package/dist/server/app-browser-state.d.ts +2 -4
- package/dist/server/app-browser-state.js +9 -4
- package/dist/server/app-browser-supplemental-refresh.js +16 -1
- package/dist/server/app-browser-visible-commit.d.ts +1 -1
- package/dist/server/app-browser-visible-commit.js +4 -14
- package/dist/server/app-elements-wire.d.ts +6 -38
- package/dist/server/app-elements-wire.js +4 -41
- package/dist/server/app-elements.d.ts +2 -2
- package/dist/server/app-elements.js +2 -2
- package/dist/server/app-history-state.d.ts +2 -2
- package/dist/server/app-history-state.js +5 -2
- package/dist/server/app-mounted-layouts.d.ts +21 -0
- package/dist/server/app-mounted-layouts.js +67 -0
- package/dist/server/app-optimistic-routing.d.ts +19 -1
- package/dist/server/app-optimistic-routing.js +43 -4
- package/dist/server/app-page-boundary-render.js +10 -14
- package/dist/server/app-page-boundary.js +2 -2
- package/dist/server/app-page-cache-finalizer.d.ts +12 -1
- package/dist/server/app-page-cache-finalizer.js +70 -29
- package/dist/server/app-page-cache.d.ts +13 -1
- package/dist/server/app-page-cache.js +31 -9
- package/dist/server/app-page-dispatch.d.ts +5 -11
- package/dist/server/app-page-dispatch.js +84 -155
- package/dist/server/app-page-element-builder.d.ts +2 -2
- package/dist/server/app-page-element-builder.js +13 -12
- package/dist/server/app-page-execution.d.ts +17 -52
- package/dist/server/app-page-execution.js +102 -95
- package/dist/server/app-page-head.d.ts +13 -0
- package/dist/server/app-page-head.js +44 -16
- package/dist/server/app-page-http-access-fallback-metadata.d.ts +1 -0
- package/dist/server/app-page-http-access-fallback-metadata.js +2 -2
- package/dist/server/app-page-layout-gate.d.ts +35 -0
- package/dist/server/app-page-layout-gate.js +50 -0
- package/dist/server/app-page-params.d.ts +0 -1
- package/dist/server/app-page-params.js +1 -14
- package/dist/server/app-page-probe.d.ts +3 -21
- package/dist/server/app-page-probe.js +4 -37
- package/dist/server/app-page-render.d.ts +2 -13
- package/dist/server/app-page-render.js +103 -234
- package/dist/server/app-page-request.d.ts +1 -3
- package/dist/server/app-page-request.js +1 -1
- package/dist/server/app-page-response.js +3 -3
- package/dist/server/app-page-route-wiring.d.ts +13 -6
- package/dist/server/app-page-route-wiring.js +86 -63
- package/dist/server/app-page-rsc-render-status.d.ts +27 -1
- package/dist/server/app-page-rsc-render-status.js +121 -13
- package/dist/server/app-page-stream.d.ts +12 -8
- package/dist/server/app-page-stream.js +4 -3
- package/dist/server/app-pages-bridge.d.ts +4 -0
- package/dist/server/app-pages-bridge.js +7 -3
- package/dist/server/app-render-dependency.d.ts +11 -4
- package/dist/server/app-render-dependency.js +86 -38
- package/dist/server/app-request-stage-dispatch.js +1 -1
- package/dist/server/app-request-stage-independent-entry.js +1 -1
- package/dist/server/app-route-handler-cache.js +2 -2
- package/dist/server/app-route-handler-dispatch.js +14 -9
- package/dist/server/app-route-handler-execution.js +11 -5
- package/dist/server/app-route-handler-policy.d.ts +1 -1
- package/dist/server/app-route-handler-policy.js +3 -3
- package/dist/server/app-route-handler-response.js +1 -1
- package/dist/server/app-route-handler-runtime.d.ts +1 -1
- package/dist/server/app-route-handler-runtime.js +28 -11
- package/dist/server/app-router-entry.js +1 -1
- package/dist/server/app-rsc-cache-busting.d.ts +12 -12
- package/dist/server/app-rsc-cache-busting.js +31 -72
- package/dist/server/app-rsc-error-handler.d.ts +2 -1
- package/dist/server/app-rsc-error-handler.js +10 -2
- package/dist/server/app-rsc-errors.d.ts +8 -0
- package/dist/server/app-rsc-errors.js +11 -1
- package/dist/server/app-rsc-handler.d.ts +5 -5
- package/dist/server/app-rsc-handler.js +80 -83
- package/dist/server/app-rsc-request-normalization.d.ts +10 -16
- package/dist/server/app-rsc-request-normalization.js +12 -18
- package/dist/server/app-rsc-response-finalizer.js +2 -2
- package/dist/server/app-rsc-response-stage.js +9 -15
- package/dist/server/app-server-action-execution.d.ts +3 -1
- package/dist/server/app-server-action-execution.js +15 -8
- package/dist/server/app-ssr-entry.d.ts +8 -0
- package/dist/server/app-ssr-entry.js +22 -16
- package/dist/server/app-ssr-stream.js +1 -1
- package/dist/server/app-visited-response-cache.d.ts +36 -1
- package/dist/server/app-visited-response-cache.js +46 -5
- package/dist/server/app-worker-stages.d.ts +37 -6
- package/dist/server/app-worker-stages.js +81 -9
- package/dist/server/artifact-compatibility.d.ts +0 -1
- package/dist/server/artifact-compatibility.js +1 -10
- package/dist/server/bfcache-identity.d.ts +7 -0
- package/dist/server/bfcache-identity.js +10 -1
- package/dist/server/cache-proof.d.ts +1 -115
- package/dist/server/cache-proof.js +1 -544
- package/dist/server/cacheability-manifest.js +1 -2
- package/dist/server/cacheability-request.js +13 -8
- package/dist/server/dev-origin-check.d.ts +2 -1
- package/dist/server/dev-origin-check.js +2 -1
- package/dist/server/dev-server.js +6 -4
- package/dist/server/headers.d.ts +6 -3
- package/dist/server/headers.js +9 -5
- package/dist/server/image-optimization.d.ts +5 -0
- package/dist/server/image-optimization.js +6 -1
- package/dist/server/isr-cache.d.ts +8 -2
- package/dist/server/isr-cache.js +30 -2
- package/dist/server/metadata-route-response.js +32 -15
- package/dist/server/middleware-matcher.js +19 -6
- package/dist/server/middleware-runtime.js +6 -2
- package/dist/server/multi-stage.d.ts +57 -12
- package/dist/server/multi-stage.js +13 -1
- package/dist/server/navigation-planner.js +1 -1
- package/dist/server/pages-api-route.js +28 -19
- package/dist/server/pages-media-type.d.ts +21 -1
- package/dist/server/pages-media-type.js +69 -5
- package/dist/server/pages-node-compat.d.ts +1 -1
- package/dist/server/pages-node-compat.js +54 -27
- package/dist/server/pages-page-data.js +2 -1
- package/dist/server/pages-page-handler.js +28 -26
- package/dist/server/pages-page-response.d.ts +9 -0
- package/dist/server/pages-page-response.js +18 -4
- package/dist/server/pages-request-pipeline.d.ts +8 -0
- package/dist/server/pages-request-pipeline.js +2 -2
- package/dist/server/pages-request-stage-entry.js +36 -14
- package/dist/server/pages-response-stage-entry.js +9 -3
- package/dist/server/pages-router-entry.js +3 -2
- package/dist/server/prod-server.d.ts +2 -2
- package/dist/server/prod-server.js +47 -9
- package/dist/server/request-error-log.d.ts +9 -0
- package/dist/server/request-error-log.js +13 -0
- package/dist/server/request-pipeline.d.ts +15 -4
- package/dist/server/request-pipeline.js +43 -15
- package/dist/server/rsc-completion-metadata.js +3 -0
- package/dist/server/shared-cache-identity.d.ts +23 -0
- package/dist/server/shared-cache-identity.js +36 -0
- package/dist/server/static-file-cache.d.ts +9 -0
- package/dist/server/static-file-cache.js +13 -2
- package/dist/server/worker-stages.d.ts +16 -3
- package/dist/server/worker-stages.js +23 -4
- package/dist/shims/cache-handler.js +2 -2
- package/dist/shims/cache-request-state.d.ts +23 -26
- package/dist/shims/cache-request-state.js +22 -57
- package/dist/shims/cache-runtime.d.ts +3 -1
- package/dist/shims/cache-runtime.js +94 -48
- package/dist/shims/cache.d.ts +16 -10
- package/dist/shims/cache.js +47 -36
- package/dist/shims/cacheability-classification.d.ts +2 -0
- package/dist/shims/cdn-cache.d.ts +22 -5
- package/dist/shims/client-hook-error.d.ts +2 -0
- package/dist/shims/client-hook-error.js +16 -1
- package/dist/shims/client-page-root.js +2 -2
- package/dist/shims/dynamic.js +9 -6
- package/dist/shims/error-boundary.js +2 -2
- package/dist/shims/fetch-cache-state.d.ts +5 -1
- package/dist/shims/fetch-cache-state.js +1 -3
- package/dist/shims/fetch-cache.d.ts +2 -1
- package/dist/shims/fetch-cache.js +39 -25
- package/dist/shims/form.js +2 -2
- package/dist/shims/headers.d.ts +10 -24
- package/dist/shims/headers.js +22 -70
- package/dist/shims/internal/cache-context-accessor.d.ts +1 -1
- package/dist/shims/internal/navigation-untracked.js +1 -1
- package/dist/shims/link.js +8 -11
- package/dist/shims/metadata.d.ts +23 -21
- package/dist/shims/metadata.js +62 -24
- package/dist/shims/navigation-server.js +1 -1
- package/dist/shims/navigation.d.ts +74 -7
- package/dist/shims/navigation.js +184 -31
- package/dist/shims/navigation.react-server.js +2 -2
- package/dist/shims/request-state-types.d.ts +3 -2
- package/dist/shims/slot.d.ts +16 -0
- package/dist/shims/slot.js +44 -9
- package/dist/shims/unified-request-context.d.ts +7 -1
- package/dist/shims/unified-request-context.js +3 -3
- package/dist/utils/cache-control-metadata.d.ts +5 -0
- package/dist/utils/cache-control-metadata.js +9 -1
- package/dist/utils/cache-life-profiles.d.ts +33 -0
- package/dist/utils/cache-life-profiles.js +111 -0
- package/dist/utils/middleware-request-headers.d.ts +14 -3
- package/dist/utils/middleware-request-headers.js +54 -7
- package/dist/utils/project.d.ts +2 -2
- package/dist/utils/project.js +3 -16
- package/dist/utils/regex.d.ts +5 -0
- package/dist/utils/regex.js +11 -1
- package/dist/utils/text-stream.d.ts +10 -5
- package/dist/utils/text-stream.js +6 -6
- package/package.json +2 -1
- package/dist/build/layout-classification-types.d.ts +0 -60
- package/dist/build/layout-classification-types.js +0 -1
- package/dist/build/layout-classification.d.ts +0 -62
- package/dist/build/layout-classification.js +0 -98
- package/dist/build/route-classification-injector.d.ts +0 -33
- package/dist/build/route-classification-injector.js +0 -59
- package/dist/build/route-classification-manifest.d.ts +0 -54
- package/dist/build/route-classification-manifest.js +0 -143
- package/dist/server/app-browser-client-reuse-manifest.d.ts +0 -11
- package/dist/server/app-browser-client-reuse-manifest.js +0 -101
- package/dist/server/app-layout-param-observation.d.ts +0 -42
- package/dist/server/app-layout-param-observation.js +0 -168
- package/dist/server/client-reuse-manifest.d.ts +0 -103
- package/dist/server/client-reuse-manifest.js +0 -209
- package/dist/server/skip-cache-proof.d.ts +0 -60
- package/dist/server/skip-cache-proof.js +0 -168
- package/dist/server/static-layout-client-reuse-proof.d.ts +0 -14
- package/dist/server/static-layout-client-reuse-proof.js +0 -33
- package/dist/utils/sorted-array.d.ts +0 -8
- package/dist/utils/sorted-array.js +0 -20
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { VINEXT_PRERENDER_SECRET_HEADER, VINEXT_REVALIDATE_HOST_HEADER } from "../utils/protocol-headers.js";
|
|
2
|
+
import { applyMiddlewareResponseHeadersToRequest } from "../utils/middleware-request-headers.js";
|
|
2
3
|
import { requestContextFromRequest } from "../config/request-context.js";
|
|
3
4
|
import { hasBasePath, stripBasePath } from "../utils/base-path.js";
|
|
4
5
|
import { VINEXT_CACHEABILITY_PROBE_QUERY_PARAM, VINEXT_EXPECTED_WORKER_VERSION_HEADER } from "./headers.js";
|
|
5
6
|
import { notFoundStaticAssetResponse } from "./http-error-responses.js";
|
|
6
|
-
import { attachRequestCfMetadata,
|
|
7
|
+
import { attachRequestCfMetadata, cloneRequestWithUrl, filterInternalHeaders, guardProtocolRelativeUrl, haveSameHeaders, stripRequestUrlFragment, withRequestHeaders } from "./request-pipeline.js";
|
|
7
8
|
import { assetPrefixPathname, isNextStaticPath } from "../utils/asset-prefix.js";
|
|
8
9
|
import { normalizePathnameForRouteMatchStrict } from "../routing/utils.js";
|
|
9
10
|
import { runWithExecutionContext } from "../shims/request-context.js";
|
|
@@ -22,7 +23,8 @@ import { resolveClientBuildFile } from "./client-build-files.js";
|
|
|
22
23
|
import { createWorkerRevalidationContext } from "./worker-revalidation-context.js";
|
|
23
24
|
import { createWorkerPrerenderDiscoveryContext, createWorkerPrerenderReadinessResponse, isWorkerPrerenderDiscoveryPath } from "./worker-prerender-discovery.js";
|
|
24
25
|
import { getPagesResponseStageCacheDisposition } from "./pages-response-stage.js";
|
|
25
|
-
import "./
|
|
26
|
+
import { adapterUsesSharedCacheIdentity, pagesCacheIdentityOrigin, pagesPageSharesAcrossHosts } from "./shared-cache-identity.js";
|
|
27
|
+
import { createSharedPagesPageCacheIdentity } from "./worker-stages.js";
|
|
26
28
|
import { consumePagesResponseStagePolicyOwner, prependResponseStageAdditiveHeaders, withResponseStageVary, withoutResponseStageVary } from "./response-stage-policy.js";
|
|
27
29
|
import * as configuredCdnCacheAdapters from "virtual:vinext-cdn-cache-adapter";
|
|
28
30
|
import { registerConfiguredImageOptimizer } from "virtual:vinext-image-adapters";
|
|
@@ -34,10 +36,14 @@ import * as pagesEntry from "virtual:vinext-pages-request-entry";
|
|
|
34
36
|
* The public pages-router-entry delegates here. Multi-stage hosts import the
|
|
35
37
|
* named request handler directly and provide their response-stage dispatcher.
|
|
36
38
|
*/
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
/**
|
|
40
|
+
* Whether middleware's request-header overrides changed the request. Next.js
|
|
41
|
+
* also copies ordinary middleware response headers onto the request; like a
|
|
42
|
+
* client's own headers, those do not opt the render out of the shared stage.
|
|
43
|
+
*/
|
|
44
|
+
function hasRequestHeaderOverrides(originalHeaders, requestHeaders, middlewareResponseHeaders) {
|
|
45
|
+
const expectedHeaders = middlewareResponseHeaders ? applyMiddlewareResponseHeadersToRequest(originalHeaders, middlewareResponseHeaders) : originalHeaders;
|
|
46
|
+
return !haveSameHeaders(expectedHeaders, requestHeaders);
|
|
41
47
|
}
|
|
42
48
|
function captureOuterResponsePolicyHeaders(stagedHeaders, transportedPolicyHeaders) {
|
|
43
49
|
return captureCdnResponsePolicyOverrides(stagedHeaders, new Headers(transportedPolicyHeaders ?? []));
|
|
@@ -90,6 +96,7 @@ function handleRequestStageLocally(request, env, ctx, dispatchResponseStage) {
|
|
|
90
96
|
return handleRequest(request, env, ctx, (stageRequest, props, _options, stageEnv, stageCtx) => dispatchResponseStage(stageRequest, stageEnv, stageCtx, props), true, "worker", ctx?.assets).then((response) => applyCdnResponseIdentityHeaders(response, originalRequest));
|
|
91
97
|
}
|
|
92
98
|
function handleRequest(request, env, platformCtx, dispatchResponseStage, forceCacheBypass, defaultHostRuntime, assets) {
|
|
99
|
+
request = stripRequestUrlFragment(request);
|
|
93
100
|
const url = new URL(request.url);
|
|
94
101
|
const trace = async () => {
|
|
95
102
|
await pagesEntry.__ensureInstrumentation?.(platformCtx);
|
|
@@ -151,7 +158,7 @@ async function handleRequestImpl(request, env, platformCtx, dispatchResponseStag
|
|
|
151
158
|
const expectedWorkerVersion = request.headers.get(VINEXT_EXPECTED_WORKER_VERSION_HEADER);
|
|
152
159
|
if (expectedWorkerVersion) filteredHeaders.set(VINEXT_EXPECTED_WORKER_VERSION_HEADER, expectedWorkerVersion);
|
|
153
160
|
}
|
|
154
|
-
request =
|
|
161
|
+
request = withRequestHeaders(request, filteredHeaders);
|
|
155
162
|
const url = new URL(request.url);
|
|
156
163
|
let pathname = url.pathname;
|
|
157
164
|
if (ctx.isPrerenderPathDiscovery && isWorkerPrerenderDiscoveryPath(pathname)) return trackedDispatchResponseStage(request, {
|
|
@@ -162,7 +169,7 @@ async function handleRequestImpl(request, env, platformCtx, dispatchResponseStag
|
|
|
162
169
|
resolvedRoutePathname: pathname
|
|
163
170
|
},
|
|
164
171
|
kind: "pages-prerender-discovery",
|
|
165
|
-
protocolVersion:
|
|
172
|
+
protocolVersion: 6,
|
|
166
173
|
requestHost: url.host,
|
|
167
174
|
stagedHeaders: null
|
|
168
175
|
}, { cache: "bypass" }, env, ctx);
|
|
@@ -212,6 +219,7 @@ async function handleRequestImpl(request, env, platformCtx, dispatchResponseStag
|
|
|
212
219
|
requestContext: requestContextFromRequest(request)
|
|
213
220
|
});
|
|
214
221
|
let speculativeRenderRequest = null;
|
|
222
|
+
let middlewareResponseHeaders;
|
|
215
223
|
const deps = {
|
|
216
224
|
assetPrefix: vinextConfig?.assetPrefix,
|
|
217
225
|
basePath,
|
|
@@ -233,7 +241,15 @@ async function handleRequestImpl(request, env, platformCtx, dispatchResponseStag
|
|
|
233
241
|
authorizeOnDemandRevalidate: typeof authorizeOnDemandRevalidate === "function" ? authorizeOnDemandRevalidate : void 0,
|
|
234
242
|
matchApiRoute: typeof matchApiRoute === "function" ? matchApiRoute : null,
|
|
235
243
|
matchPageRoute: typeof matchPageRoute === "function" ? matchPageRoute : null,
|
|
236
|
-
runMiddleware: typeof runMiddleware === "function" ?
|
|
244
|
+
runMiddleware: typeof runMiddleware === "function" ? async (middlewareInput, middlewareCtx, middlewareOptions) => {
|
|
245
|
+
const result = await wrapMiddlewareWithBasePath(runMiddleware, basePath, hadBasePath)(middlewareInput, middlewareCtx, middlewareOptions);
|
|
246
|
+
middlewareResponseHeaders = void 0;
|
|
247
|
+
if (result.responseHeaders) {
|
|
248
|
+
middlewareResponseHeaders = new Headers();
|
|
249
|
+
for (const [key, value] of result.responseHeaders) middlewareResponseHeaders.append(key, value);
|
|
250
|
+
}
|
|
251
|
+
return result;
|
|
252
|
+
} : null,
|
|
237
253
|
renderPage: (req, resolvedUrl, options, stagedHeaders) => {
|
|
238
254
|
if (options?.renderErrorPageOnMiss === false && req.body !== null && !req.bodyUsed) speculativeRenderRequest = req;
|
|
239
255
|
const stageRequest = speculativeRenderRequest === req && req.body !== null && !req.bodyUsed ? attachRequestCfMetadata(req.clone(), req) : req;
|
|
@@ -242,11 +258,12 @@ async function handleRequestImpl(request, env, platformCtx, dispatchResponseStag
|
|
|
242
258
|
authorizeOnDemandRevalidate: typeof authorizeOnDemandRevalidate === "function" ? authorizeOnDemandRevalidate : void 0,
|
|
243
259
|
hasRequestAwareDocument: hasRequestAwareDocument === true,
|
|
244
260
|
request: req,
|
|
245
|
-
requestHeadersChanged:
|
|
261
|
+
requestHeadersChanged: hasRequestHeaderOverrides(filteredHeaders, req.headers, middlewareResponseHeaders),
|
|
246
262
|
routeDataKind: matchedPage?.route.dataKind,
|
|
247
263
|
stagedHeaders
|
|
248
264
|
});
|
|
249
265
|
const isSharedStaticPage = cache === "shared" && matchedPage?.route.dataKind === "static";
|
|
266
|
+
const sharedAcrossHosts = (cache === "shared" || probeMode !== null) && pagesPageSharesAcrossHosts(matchedPage?.route) && adapterUsesSharedCacheIdentity();
|
|
250
267
|
const transportedPolicyHeaders = isSharedStaticPage ? withoutResponseStageVary(responseStagePolicyHeaders) : withResponseStageVary(responseStagePolicyHeaders, stagedHeaders?.get("Vary"));
|
|
251
268
|
const responseStageProps = () => ({
|
|
252
269
|
buildId: pagesEntry.buildId,
|
|
@@ -257,17 +274,22 @@ async function handleRequestImpl(request, env, platformCtx, dispatchResponseStag
|
|
|
257
274
|
resolvedRoutePathname: new URL(resolvedUrl, req.url).pathname
|
|
258
275
|
},
|
|
259
276
|
kind: "pages-page",
|
|
260
|
-
protocolVersion:
|
|
277
|
+
protocolVersion: 6,
|
|
261
278
|
requestHost: new URL(req.url).host,
|
|
262
279
|
renderOptions: isDataReq ? {
|
|
263
280
|
...options,
|
|
264
281
|
originalUrl: originalRenderUrl
|
|
265
282
|
} : options ?? null,
|
|
266
283
|
resolvedUrl,
|
|
284
|
+
sharedAcrossHosts,
|
|
267
285
|
stagedHeaders: isSharedStaticPage ? null : [...stagedHeaders ?? new Headers()]
|
|
268
286
|
});
|
|
269
287
|
const isHeadRequest = req.method.toUpperCase() === "HEAD";
|
|
270
|
-
const
|
|
288
|
+
const props = responseStageProps();
|
|
289
|
+
const responsePromise = trackedDispatchResponseStage(stageRequest, props, cache === "shared" && sharedAcrossHosts ? {
|
|
290
|
+
cache,
|
|
291
|
+
cacheIdentity: createSharedPagesPageCacheIdentity(stageRequest, props, pagesCacheIdentityOrigin(stageRequest.url, i18nConfig))
|
|
292
|
+
} : { cache }, env, ctx).then((response) => {
|
|
271
293
|
const consumed = consumePagesResponseStagePolicyOwner(response);
|
|
272
294
|
if (cache === "shared") {
|
|
273
295
|
if (isSharedStaticPage && stagedHeaders) prependResponseStageAdditiveHeaders(consumed.response.headers, stagedHeaders);
|
|
@@ -297,14 +319,14 @@ async function handleRequestImpl(request, env, platformCtx, dispatchResponseStag
|
|
|
297
319
|
resolvedRoutePathname: new URL(apiUrl, req.url).pathname
|
|
298
320
|
},
|
|
299
321
|
kind: "pages-api",
|
|
300
|
-
protocolVersion:
|
|
322
|
+
protocolVersion: 6,
|
|
301
323
|
requestHost: new URL(req.url).host,
|
|
302
324
|
stagedHeaders: [...stagedHeaders]
|
|
303
325
|
});
|
|
304
326
|
const cache = forceCacheBypass || probeMode ? "bypass" : getPagesResponseStageCacheDisposition({
|
|
305
327
|
authorizeOnDemandRevalidate: typeof authorizeOnDemandRevalidate === "function" ? authorizeOnDemandRevalidate : void 0,
|
|
306
328
|
request: req,
|
|
307
|
-
requestHeadersChanged:
|
|
329
|
+
requestHeadersChanged: hasRequestHeaderOverrides(filteredHeaders, req.headers, middlewareResponseHeaders),
|
|
308
330
|
stagedHeaders
|
|
309
331
|
});
|
|
310
332
|
const dispatched = trackedDispatchResponseStage(req, responseStageProps(), { cache }, env, ctx);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { preserveFullyBufferedBodyMetadata } from "./fully-buffered-response.js";
|
|
2
2
|
import "../shims/unified-request-context.js";
|
|
3
3
|
import { runWithExecutionContext } from "../shims/request-context.js";
|
|
4
|
-
import { beginRouteCacheability } from "../shims/cacheability-classification.js";
|
|
4
|
+
import { beginRouteCacheability, markRouteCacheabilityDynamic } from "../shims/cacheability-classification.js";
|
|
5
5
|
import { validateCdnRequest } from "./cache-control.js";
|
|
6
6
|
import { createWorkerRevalidationContext } from "./worker-revalidation-context.js";
|
|
7
7
|
import { createWorkerPrerenderReadinessResponse } from "./worker-prerender-discovery.js";
|
|
@@ -57,6 +57,12 @@ async function renderPagesResponse(request, env, platformCtx, props, stagedHeade
|
|
|
57
57
|
...ctx,
|
|
58
58
|
isStoredEntryRegeneration: true
|
|
59
59
|
};
|
|
60
|
+
let runtimeDataKind;
|
|
61
|
+
const runtimeDataKindIsRequestTime = () => {
|
|
62
|
+
if (props.kind !== "pages-page") return false;
|
|
63
|
+
runtimeDataKind ??= pagesEntry.getRuntimePageDataKind(props.resolvedUrl, request);
|
|
64
|
+
return runtimeDataKind === "server" || runtimeDataKind === "initial";
|
|
65
|
+
};
|
|
60
66
|
const render = async (cacheabilityContext) => {
|
|
61
67
|
if (props.kind === "pages-prerender-discovery") {
|
|
62
68
|
const readinessResponse = createWorkerPrerenderReadinessResponse(cacheabilityContext, request);
|
|
@@ -77,6 +83,7 @@ async function renderPagesResponse(request, env, platformCtx, props, stagedHeade
|
|
|
77
83
|
});
|
|
78
84
|
}
|
|
79
85
|
if (typeof pagesEntry.renderPage !== "function") return new Response("This page could not be found", { status: 404 });
|
|
86
|
+
if (props.sharedAcrossHosts && runtimeDataKindIsRequestTime()) runWithExecutionContext(cacheabilityContext, () => markRouteCacheabilityDynamic("getInitialProps render shares a cache entry across hosts"));
|
|
80
87
|
return stripStreamedHtmlContentLength(await pagesEntry.renderPage(request, props.resolvedUrl, null, cacheabilityContext, renderHeaders, props.renderOptions ?? void 0, initialResponseHeaders));
|
|
81
88
|
};
|
|
82
89
|
const handle = async (cacheabilityContext) => stripInheritedResponseStageCookies(await render(cacheabilityContext), renderHeaders);
|
|
@@ -94,9 +101,8 @@ async function renderPagesResponse(request, env, platformCtx, props, stagedHeade
|
|
|
94
101
|
resolvedRoutePathname: props.cacheability.resolvedRoutePathname
|
|
95
102
|
}, handle);
|
|
96
103
|
if (props.kind !== "pages-page") return response;
|
|
97
|
-
const runtimeDataKind = pagesEntry.getRuntimePageDataKind(props.resolvedUrl, request);
|
|
98
104
|
const headers = new Headers(response.headers);
|
|
99
|
-
headers.set(PAGES_RESPONSE_STAGE_POLICY_OWNER_HEADER,
|
|
105
|
+
headers.set(PAGES_RESPONSE_STAGE_POLICY_OWNER_HEADER, runtimeDataKindIsRequestTime() ? "request-time" : "static");
|
|
100
106
|
return preserveFullyBufferedBodyMetadata(response, new Response(response.body, {
|
|
101
107
|
headers,
|
|
102
108
|
status: response.status,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { VINEXT_CACHEABILITY_PROBE_HEADER, VINEXT_CACHEABILITY_PROBE_QUERY_PARAM } from "./headers.js";
|
|
2
|
-
import { cloneRequestWithHeaders, cloneRequestWithUrl } from "./request-pipeline.js";
|
|
2
|
+
import { cloneRequestWithHeaders, cloneRequestWithUrl, stripRequestUrlFragment } from "./request-pipeline.js";
|
|
3
3
|
import { runWithExecutionContext } from "../shims/request-context.js";
|
|
4
4
|
import { getCdnCacheAdapter } from "../shims/cdn-cache.js";
|
|
5
5
|
import { validateCdnRequest } from "./cache-control.js";
|
|
@@ -52,7 +52,8 @@ async function handleSingleStageRequest(request, env, platformCtx) {
|
|
|
52
52
|
return finalize ? finalize(response, ctx) : response;
|
|
53
53
|
}
|
|
54
54
|
var pages_router_entry_default = { fetch(request, env, ctx) {
|
|
55
|
-
const
|
|
55
|
+
const strippedRequest = stripRequestUrlFragment(request);
|
|
56
|
+
const handle = () => handleSingleStageRequest(strippedRequest, env, ctx);
|
|
56
57
|
return ctx && typeof ctx.waitUntil === "function" ? runWithExecutionContext(ctx, handle) : handle();
|
|
57
58
|
} };
|
|
58
59
|
//#endregion
|
|
@@ -102,11 +102,11 @@ declare function sendCompressed(req: IncomingMessage, res: ServerResponse, body:
|
|
|
102
102
|
* Without a cache, falls back to async filesystem probing (still non-blocking,
|
|
103
103
|
* unlike the old sync existsSync/statSync approach).
|
|
104
104
|
*
|
|
105
|
-
* `
|
|
105
|
+
* `stagedHeaders` go on every response for the file. `representationHeaders` go
|
|
106
106
|
* only on responses that carry the file's bytes (200 and 206), never on a 304,
|
|
107
107
|
* 412, 416 or 405.
|
|
108
108
|
*/
|
|
109
|
-
declare function tryServeStatic(req: IncomingMessage, res: ServerResponse, clientDir: string, pathname: string, compress: boolean, cache?: StaticFileCache,
|
|
109
|
+
declare function tryServeStatic(req: IncomingMessage, res: ServerResponse, clientDir: string, pathname: string, compress: boolean, cache?: StaticFileCache, stagedHeaders?: Record<string, string | string[]>, statusCode?: number, representationHeaders?: Record<string, string>): Promise<boolean>;
|
|
110
110
|
/**
|
|
111
111
|
* Convert a Node.js IncomingMessage to a Web Request object.
|
|
112
112
|
*
|
|
@@ -8,7 +8,7 @@ import { getRepeatedSlashRedirect, isOpenRedirectShaped, sendRepeatedSlashRedire
|
|
|
8
8
|
import { readStaticFileSignal } from "./static-file-signal.js";
|
|
9
9
|
import { canonicalizeRequestPathname, filterInternalHeaders } from "./request-pipeline.js";
|
|
10
10
|
import { ASSET_PREFIX_URL_DIR, assetPrefixPathname, isAbsoluteAssetPrefix, isAssetPrefixBuildAsset } from "../utils/asset-prefix.js";
|
|
11
|
-
import { StaticFileCache, contentTypeForPath, etagFromFilenameHash } from "./static-file-cache.js";
|
|
11
|
+
import { StaticFileCache, contentTypeForPath, etagFromFilenameHash, staticFileCacheControl } from "./static-file-cache.js";
|
|
12
12
|
import { normalizePathnameForRouteMatchStrict } from "../routing/utils.js";
|
|
13
13
|
import { resolveRequestHost, resolveRequestProtocol, resolveTrustedForwardedHost, trustProxy, trustedHosts } from "./proxy-trust.js";
|
|
14
14
|
import { normalizePath } from "./normalize-path.js";
|
|
@@ -19,7 +19,7 @@ import { parseHttpDate } from "./http-date.js";
|
|
|
19
19
|
import { evaluateStaticPreconditions } from "./http-conditional.js";
|
|
20
20
|
import { setPagesClientAssets } from "./pages-client-assets.js";
|
|
21
21
|
import { signalFromNodeResponse } from "./node-response-signal.js";
|
|
22
|
-
import { DEFAULT_DEVICE_SIZES, DEFAULT_IMAGE_SIZES, IMAGE_RESPONSE_CACHE_STATE, INVALID_IMAGE_SOURCE_MESSAGE, isImageOptimizationPath, isImageSourceBodyStatus, isSafeImageContentType, parseImageParams, readImageOptimizationSignal } from "./image-optimization.js";
|
|
22
|
+
import { DEFAULT_DEVICE_SIZES, DEFAULT_IMAGE_SIZES, IMAGE_RESPONSE_CACHE_STATE, INVALID_IMAGE_SOURCE_MESSAGE, MUTABLE_IMAGE_SOURCE_CACHE_CONTROL, isImageOptimizationPath, isImageSourceBodyStatus, isSafeImageContentType, parseImageParams, readImageOptimizationSignal } from "./image-optimization.js";
|
|
23
23
|
import { installSocketErrorBackstop } from "./socket-error-backstop.js";
|
|
24
24
|
import { collectInlineCssManifest } from "../build/inline-css.js";
|
|
25
25
|
import { readTrustedRevalidationHostname } from "./revalidation-host.js";
|
|
@@ -284,6 +284,16 @@ function readHeaderCaseInsensitive(headersRecord, name) {
|
|
|
284
284
|
const value = headersRecord[key];
|
|
285
285
|
return Array.isArray(value) ? value.join(", ") : value;
|
|
286
286
|
}
|
|
287
|
+
/** Spell a header's name as `name`, so spreading the record replaces that key. */
|
|
288
|
+
function withHeaderName(headersRecord, name) {
|
|
289
|
+
const lowerName = name.toLowerCase();
|
|
290
|
+
const key = Object.keys(headersRecord).find((entry) => entry !== name && entry.toLowerCase() === lowerName);
|
|
291
|
+
if (key === void 0) return headersRecord;
|
|
292
|
+
const { [key]: value, ...rest } = headersRecord;
|
|
293
|
+
const existing = rest[name];
|
|
294
|
+
rest[name] = existing === void 0 ? value : [existing, value].flat();
|
|
295
|
+
return rest;
|
|
296
|
+
}
|
|
287
297
|
/** Remove one field name from a Vary header, dropping the header if it empties. */
|
|
288
298
|
function omitVaryToken(headers, token) {
|
|
289
299
|
const varyKey = Object.keys(headers).find((key) => key.toLowerCase() === "vary");
|
|
@@ -464,6 +474,18 @@ function staticCacheLookupPath(pathname) {
|
|
|
464
474
|
if (lookupPath.startsWith("/.vite/") || lookupPath === "/.vite") return null;
|
|
465
475
|
return lookupPath;
|
|
466
476
|
}
|
|
477
|
+
/**
|
|
478
|
+
* Give a Node image passthrough Next.js's image Cache-Control instead of the
|
|
479
|
+
* public-file default: a hashed build asset keeps its immutable default, and
|
|
480
|
+
* any other source is revalidated after the default `images.minimumCacheTTL`.
|
|
481
|
+
*/
|
|
482
|
+
function withImageSourceCacheControl(headers, sourcePath) {
|
|
483
|
+
if (sourcePath.includes(`/_next/static/`)) return headers;
|
|
484
|
+
return {
|
|
485
|
+
...headers,
|
|
486
|
+
"Cache-Control": MUTABLE_IMAGE_SOURCE_CACHE_CONTROL
|
|
487
|
+
};
|
|
488
|
+
}
|
|
467
489
|
/** Pathnames the Pages Router serves from routes rather than the client directory. */
|
|
468
490
|
function isPagesFilesystemExcludedPath(pathname, phase) {
|
|
469
491
|
return pathname === "/" || pathname === "/api" || pathname.startsWith("/api/") || phase === "direct" && pathname.startsWith(`/_next/static/`);
|
|
@@ -479,12 +501,13 @@ function isPagesFilesystemExcludedPath(pathname, phase) {
|
|
|
479
501
|
* Without a cache, falls back to async filesystem probing (still non-blocking,
|
|
480
502
|
* unlike the old sync existsSync/statSync approach).
|
|
481
503
|
*
|
|
482
|
-
* `
|
|
504
|
+
* `stagedHeaders` go on every response for the file. `representationHeaders` go
|
|
483
505
|
* only on responses that carry the file's bytes (200 and 206), never on a 304,
|
|
484
506
|
* 412, 416 or 405.
|
|
485
507
|
*/
|
|
486
|
-
async function tryServeStatic(req, res, clientDir, pathname, compress, cache,
|
|
508
|
+
async function tryServeStatic(req, res, clientDir, pathname, compress, cache, stagedHeaders, statusCode, representationHeaders) {
|
|
487
509
|
if (pathname === "/") return false;
|
|
510
|
+
const extraHeaders = stagedHeaders && withHeaderName(stagedHeaders, "Cache-Control");
|
|
488
511
|
const responseStatus = statusCode ?? 200;
|
|
489
512
|
const omitBody = isNoBodyResponseStatus(responseStatus);
|
|
490
513
|
const requestRange = req.method === "GET" || req.method === "HEAD" ? req.headers.range : void 0;
|
|
@@ -610,7 +633,7 @@ async function tryServeStatic(req, res, clientDir, pathname, compress, cache, ex
|
|
|
610
633
|
const ext = path.extname(resolved.path);
|
|
611
634
|
const ct = contentTypeForPath(resolved.path);
|
|
612
635
|
const isHashed = pathname.includes(`/${ASSET_PREFIX_URL_DIR}/`);
|
|
613
|
-
const cacheControl = isHashed
|
|
636
|
+
const cacheControl = staticFileCacheControl(isHashed);
|
|
614
637
|
const etag = isHashed && etagFromFilenameHash(resolved.path, ext) || `W/"${resolved.size}-${Math.floor(resolved.mtimeMs / 1e3)}"`;
|
|
615
638
|
const baseHeaders = {
|
|
616
639
|
"Content-Type": ct,
|
|
@@ -798,6 +821,15 @@ async function statIfFile(filePath) {
|
|
|
798
821
|
}
|
|
799
822
|
}
|
|
800
823
|
/**
|
|
824
|
+
* Node's parser keeps a `#fragment` sent on the request line in `req.url`.
|
|
825
|
+
* Next.js rebuilds request URLs from pathname + search, so neither routing,
|
|
826
|
+
* middleware nor handlers observe one; drop it before anything reads the URL.
|
|
827
|
+
*/
|
|
828
|
+
function stripNodeRequestUrlFragment(req) {
|
|
829
|
+
const hashIndex = req.url?.indexOf("#") ?? -1;
|
|
830
|
+
if (hashIndex !== -1) req.url = req.url?.slice(0, hashIndex);
|
|
831
|
+
}
|
|
832
|
+
/**
|
|
801
833
|
* Convert a Node.js IncomingMessage to a Web Request object.
|
|
802
834
|
*
|
|
803
835
|
* When `urlOverride` is provided, it is used as the path + query string
|
|
@@ -1182,7 +1214,7 @@ async function startAppRouterServer(options) {
|
|
|
1182
1214
|
"X-Content-Type-Options": "nosniff",
|
|
1183
1215
|
"Content-Disposition": imageConfig?.contentDispositionType === "attachment" ? "attachment" : "inline"
|
|
1184
1216
|
};
|
|
1185
|
-
const serveSource = (sourcePath) => tryServeStatic(req, res, clientDir, sourcePath, false, staticCache, imageSecurityHeaders, void 0, IMAGE_REPRESENTATION_HEADERS);
|
|
1217
|
+
const serveSource = (sourcePath) => tryServeStatic(req, res, clientDir, sourcePath, false, staticCache, withImageSourceCacheControl(imageSecurityHeaders, sourcePath), void 0, IMAGE_REPRESENTATION_HEADERS);
|
|
1186
1218
|
const sourceUrl = new URL(params.imageUrl, request.url);
|
|
1187
1219
|
let sourcePathname = null;
|
|
1188
1220
|
try {
|
|
@@ -1299,6 +1331,7 @@ async function startAppRouterServer(options) {
|
|
|
1299
1331
|
}
|
|
1300
1332
|
};
|
|
1301
1333
|
const handleRequest = async (req, res) => {
|
|
1334
|
+
stripNodeRequestUrlFragment(req);
|
|
1302
1335
|
try {
|
|
1303
1336
|
await ensureInstrumentation();
|
|
1304
1337
|
} catch (error) {
|
|
@@ -1319,7 +1352,7 @@ async function startAppRouterServer(options) {
|
|
|
1319
1352
|
},
|
|
1320
1353
|
getStatus: () => res.statusCode,
|
|
1321
1354
|
headers,
|
|
1322
|
-
isRsc:
|
|
1355
|
+
isRsc: headers.get("RSC") === "1",
|
|
1323
1356
|
method: req.method ?? "GET",
|
|
1324
1357
|
target
|
|
1325
1358
|
});
|
|
@@ -1434,6 +1467,7 @@ async function createPagesRouterRequestHandler(options) {
|
|
|
1434
1467
|
});
|
|
1435
1468
|
const staticCache = await StaticFileCache.create(clientDir);
|
|
1436
1469
|
const handleRequest = async (req, res) => {
|
|
1470
|
+
stripNodeRequestUrlFragment(req);
|
|
1437
1471
|
try {
|
|
1438
1472
|
await ensureInstrumentation();
|
|
1439
1473
|
} catch (error) {
|
|
@@ -1646,7 +1680,11 @@ async function createPagesRouterRequestHandler(options) {
|
|
|
1646
1680
|
...options,
|
|
1647
1681
|
originalUrl: originalRenderUrl
|
|
1648
1682
|
}, stagedHeaders?.has("Cache-Control") ? new Headers({ "Cache-Control": stagedHeaders.get("Cache-Control") }) : void 0) : null,
|
|
1649
|
-
handleApi: typeof handleApi === "function" ? (request, apiUrl
|
|
1683
|
+
handleApi: typeof handleApi === "function" ? (request, apiUrl, _ctx, stagedHeaders) => {
|
|
1684
|
+
stagedHeaders.delete("Content-Length");
|
|
1685
|
+
return handleApi(request, apiUrl, createNodeExecutionContext(), resolveTrustedNodeRevalidateOrigin(req, host, port), "node", stagedHeaders);
|
|
1686
|
+
} : null,
|
|
1687
|
+
handleApiAppliesStagedHeaders: true,
|
|
1650
1688
|
serveFilesystemRoute: async (requestPathname, stagedHeaders, phase, resolvedUrl, _request, resolvedPathnameHasBasePath) => {
|
|
1651
1689
|
if (resolvedPathnameHasBasePath && isImageOptimizationPath(requestPathname)) {
|
|
1652
1690
|
for (const [name, value] of Object.entries(stagedHeaders)) res.setHeader(name, value);
|
|
@@ -1667,7 +1705,7 @@ async function createPagesRouterRequestHandler(options) {
|
|
|
1667
1705
|
"X-Content-Type-Options": "nosniff",
|
|
1668
1706
|
"Content-Disposition": pagesImageConfig?.contentDispositionType === "attachment" ? "attachment" : "inline"
|
|
1669
1707
|
};
|
|
1670
|
-
const serveSource = (sourcePath) => tryServeStatic(req, res, clientDir, sourcePath, false, staticCache, imageSecurityHeaders, void 0, IMAGE_REPRESENTATION_HEADERS);
|
|
1708
|
+
const serveSource = (sourcePath) => tryServeStatic(req, res, clientDir, sourcePath, false, staticCache, withImageSourceCacheControl(imageSecurityHeaders, sourcePath), void 0, IMAGE_REPRESENTATION_HEADERS);
|
|
1671
1709
|
const sourceUrl = new URL(params.imageUrl, webRequest.url);
|
|
1672
1710
|
let sourcePathname = null;
|
|
1673
1711
|
try {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
//#region src/server/request-error-log.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Logs an error vinext also passes to instrumentation's `onRequestError`, as
|
|
4
|
+
* `next start` logs it. `VINEXT_QUIET=1` turns these logs off, like Next.js'
|
|
5
|
+
* `quiet` server option, so an `onRequestError` that redacts errors before
|
|
6
|
+
* recording them is the only place they reach.
|
|
7
|
+
*/
|
|
8
|
+
export declare function logRequestError(...args: unknown[]): void;
|
|
9
|
+
//#endregion
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//#region src/server/request-error-log.ts
|
|
2
|
+
/**
|
|
3
|
+
* Logs an error vinext also passes to instrumentation's `onRequestError`, as
|
|
4
|
+
* `next start` logs it. `VINEXT_QUIET=1` turns these logs off, like Next.js'
|
|
5
|
+
* `quiet` server option, so an `onRequestError` that redacts errors before
|
|
6
|
+
* recording them is the only place they reach.
|
|
7
|
+
*/
|
|
8
|
+
function logRequestError(...args) {
|
|
9
|
+
if (process.env.VINEXT_QUIET === "1") return;
|
|
10
|
+
console.error(...args);
|
|
11
|
+
}
|
|
12
|
+
//#endregion
|
|
13
|
+
export { logRequestError };
|
|
@@ -73,7 +73,6 @@ type ResolvePublicFileRouteOptions = {
|
|
|
73
73
|
middlewareContext: StaticFileSignalContext & {
|
|
74
74
|
requestHeaders?: Headers | null;
|
|
75
75
|
};
|
|
76
|
-
pathname: string;
|
|
77
76
|
publicFiles: ReadonlySet<string>;
|
|
78
77
|
request: Request;
|
|
79
78
|
};
|
|
@@ -82,7 +81,7 @@ type ResolvePublicFileRouteOptions = {
|
|
|
82
81
|
*
|
|
83
82
|
* Public files are checked after middleware and before afterFiles/fallback
|
|
84
83
|
* rewrites. The generated App Router entry provides the public-file set; this
|
|
85
|
-
* helper owns
|
|
84
|
+
* helper owns existence-first method enforcement and
|
|
86
85
|
* static-file signaling. Missing mutation targets continue through routing.
|
|
87
86
|
*/
|
|
88
87
|
export declare function resolvePublicFileRoute(options: ResolvePublicFileRouteOptions): Response | null;
|
|
@@ -91,8 +90,8 @@ export declare function normalizeTrailingSlashPathname(pathname: string, trailin
|
|
|
91
90
|
* Check if the pathname needs a trailing slash redirect, and return the
|
|
92
91
|
* redirect Response if so.
|
|
93
92
|
*
|
|
94
|
-
* Follows Next.js behavior
|
|
95
|
-
*
|
|
93
|
+
* Follows Next.js behavior, whose internal trailing-slash redirects cover
|
|
94
|
+
* every path, `/api` included:
|
|
96
95
|
* - The root path `/` is never redirected
|
|
97
96
|
* - If `trailingSlash` is true, redirect `/about` → `/about/`
|
|
98
97
|
* - If `trailingSlash` is true, redirect file-looking `/file.ext/` → `/file.ext`
|
|
@@ -181,6 +180,12 @@ export declare function attachRequestCfMetadata(target: Request, source: Request
|
|
|
181
180
|
* a RequestInit with best-effort metadata.
|
|
182
181
|
*/
|
|
183
182
|
export declare function cloneRequestWithHeaders(request: Request, headers: Headers): Request;
|
|
183
|
+
export declare function haveSameHeaders(first: Headers, second: Headers): boolean;
|
|
184
|
+
/**
|
|
185
|
+
* `cloneRequestWithHeaders`, except that a native request whose headers
|
|
186
|
+
* already match is returned as is, so its body stays where it is.
|
|
187
|
+
*/
|
|
188
|
+
export declare function withRequestHeaders(request: Request, headers: Headers): Request;
|
|
184
189
|
/**
|
|
185
190
|
* Clone a Request while overriding the URL, preserving headers and metadata
|
|
186
191
|
* when possible.
|
|
@@ -194,5 +199,11 @@ export declare function cloneRequestWithHeaders(request: Request, headers: Heade
|
|
|
194
199
|
* exists.
|
|
195
200
|
*/
|
|
196
201
|
export declare function cloneRequestWithUrl(request: Request, url: string): Request;
|
|
202
|
+
/**
|
|
203
|
+
* Drop a `#fragment` the host kept from the request line. Next.js rebuilds
|
|
204
|
+
* request URLs from pathname + search, so neither middleware nor handlers
|
|
205
|
+
* ever observe one, and pathname-keyed cache entries must not either.
|
|
206
|
+
*/
|
|
207
|
+
export declare function stripRequestUrlFragment(request: Request): Request;
|
|
197
208
|
//#endregion
|
|
198
209
|
export { INTERNAL_HEADERS, VINEXT_INTERNAL_HEADERS, createStaticFileSignal, getRepeatedSlashRedirect, hasBasePath, isOpenRedirectShaped, sendRepeatedSlashRedirect, stripBasePath };
|
|
@@ -84,7 +84,8 @@ function guardProtocolRelativeUrl(rawPathname, search = "") {
|
|
|
84
84
|
if (isOpenRedirectShaped(rawPathname)) return notFoundResponse();
|
|
85
85
|
return null;
|
|
86
86
|
}
|
|
87
|
-
const
|
|
87
|
+
const SLASHED_FILE_PATHNAME_RE = /^\/(?:[^/]+\/)*[^/]+\.\w+\/$/;
|
|
88
|
+
const UNSLASHED_NON_FILE_PATHNAME_RE = /^\/(?:[^/]+\/)*[^/.]+$/;
|
|
88
89
|
function isWellKnownPathname(pathname) {
|
|
89
90
|
return pathname === "/.well-known" || pathname.startsWith("/.well-known/");
|
|
90
91
|
}
|
|
@@ -93,37 +94,32 @@ function isWellKnownPathname(pathname) {
|
|
|
93
94
|
*
|
|
94
95
|
* Public files are checked after middleware and before afterFiles/fallback
|
|
95
96
|
* rewrites. The generated App Router entry provides the public-file set; this
|
|
96
|
-
* helper owns
|
|
97
|
+
* helper owns existence-first method enforcement and
|
|
97
98
|
* static-file signaling. Missing mutation targets continue through routing.
|
|
98
99
|
*/
|
|
99
100
|
function resolvePublicFileRoute(options) {
|
|
100
|
-
if (options.pathname.endsWith(".rsc")) return null;
|
|
101
101
|
if (!options.publicFiles.has(options.cleanPathname)) return null;
|
|
102
102
|
if (options.request.method !== "GET" && options.request.method !== "HEAD") return methodNotAllowedResponse("GET, HEAD", { headers: options.middlewareContext.headers ?? void 0 });
|
|
103
103
|
const { requestHeaders } = options.middlewareContext;
|
|
104
104
|
return createStaticFileSignal(options.cleanPathname, options.middlewareContext, requestHeaders ? buildRequestHeadersFromMiddlewareResponse(options.request.headers, requestHeaders) : null);
|
|
105
105
|
}
|
|
106
106
|
function normalizeTrailingSlashPathname(pathname, trailingSlash) {
|
|
107
|
-
if (pathname === "/"
|
|
108
|
-
const hasTrailing = pathname.endsWith("/");
|
|
107
|
+
if (pathname === "/") return null;
|
|
109
108
|
if (trailingSlash) {
|
|
110
109
|
if (isWellKnownPathname(pathname)) return null;
|
|
111
|
-
if (
|
|
112
|
-
|
|
113
|
-
return normalized === pathname ? null : normalized;
|
|
114
|
-
}
|
|
115
|
-
if (!hasTrailing && !pathname.endsWith(".rsc")) return `${pathname}/`;
|
|
110
|
+
if (SLASHED_FILE_PATHNAME_RE.test(pathname)) return pathname.slice(0, -1);
|
|
111
|
+
if (UNSLASHED_NON_FILE_PATHNAME_RE.test(pathname)) return `${pathname}/`;
|
|
116
112
|
return null;
|
|
117
113
|
}
|
|
118
|
-
if (
|
|
114
|
+
if (pathname.endsWith("/")) return removeTrailingSlash(pathname);
|
|
119
115
|
return null;
|
|
120
116
|
}
|
|
121
117
|
/**
|
|
122
118
|
* Check if the pathname needs a trailing slash redirect, and return the
|
|
123
119
|
* redirect Response if so.
|
|
124
120
|
*
|
|
125
|
-
* Follows Next.js behavior
|
|
126
|
-
*
|
|
121
|
+
* Follows Next.js behavior, whose internal trailing-slash redirects cover
|
|
122
|
+
* every path, `/api` included:
|
|
127
123
|
* - The root path `/` is never redirected
|
|
128
124
|
* - If `trailingSlash` is true, redirect `/about` → `/about/`
|
|
129
125
|
* - If `trailingSlash` is true, redirect file-looking `/file.ext/` → `/file.ext`
|
|
@@ -137,7 +133,7 @@ function normalizeTrailingSlashPathname(pathname, trailingSlash) {
|
|
|
137
133
|
* @returns A 308 redirect Response, or null if no redirect is needed
|
|
138
134
|
*/
|
|
139
135
|
function normalizeTrailingSlash(pathname, basePath, trailingSlash, search) {
|
|
140
|
-
if (pathname === "/"
|
|
136
|
+
if (pathname === "/") return null;
|
|
141
137
|
if (isOpenRedirectShaped(pathname)) return notFoundResponse();
|
|
142
138
|
const normalizedPathname = normalizeTrailingSlashPathname(pathname, trailingSlash);
|
|
143
139
|
if (normalizedPathname === null) return null;
|
|
@@ -407,6 +403,26 @@ function cloneRequestWithHeaders(request, headers) {
|
|
|
407
403
|
}
|
|
408
404
|
return attachRequestCfMetadata(cloned, request);
|
|
409
405
|
}
|
|
406
|
+
function haveSameHeaders(first, second) {
|
|
407
|
+
const firstEntries = [...first];
|
|
408
|
+
const secondEntries = [...second];
|
|
409
|
+
return firstEntries.length === secondEntries.length && firstEntries.every(([name, value], index) => name === secondEntries[index]?.[0] && value === secondEntries[index]?.[1]);
|
|
410
|
+
}
|
|
411
|
+
function isNativeRequest(request) {
|
|
412
|
+
try {
|
|
413
|
+
Reflect.get(Request.prototype, "url", request);
|
|
414
|
+
return true;
|
|
415
|
+
} catch {
|
|
416
|
+
return false;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
/**
|
|
420
|
+
* `cloneRequestWithHeaders`, except that a native request whose headers
|
|
421
|
+
* already match is returned as is, so its body stays where it is.
|
|
422
|
+
*/
|
|
423
|
+
function withRequestHeaders(request, headers) {
|
|
424
|
+
return isNativeRequest(request) && haveSameHeaders(headers, request.headers) ? request : cloneRequestWithHeaders(request, headers);
|
|
425
|
+
}
|
|
410
426
|
/**
|
|
411
427
|
* Clone a Request while overriding the URL, preserving headers and metadata
|
|
412
428
|
* when possible.
|
|
@@ -443,5 +459,17 @@ function cloneRequestWithUrl(request, url) {
|
|
|
443
459
|
}
|
|
444
460
|
return attachRequestCfMetadata(cloned, request);
|
|
445
461
|
}
|
|
462
|
+
/**
|
|
463
|
+
* Drop a `#fragment` the host kept from the request line. Next.js rebuilds
|
|
464
|
+
* request URLs from pathname + search, so neither middleware nor handlers
|
|
465
|
+
* ever observe one, and pathname-keyed cache entries must not either.
|
|
466
|
+
*/
|
|
467
|
+
function stripRequestUrlFragment(request) {
|
|
468
|
+
const hashIndex = request.url.indexOf("#");
|
|
469
|
+
if (hashIndex === -1) return request;
|
|
470
|
+
const signal = request.signal;
|
|
471
|
+
const stripped = cloneRequestWithUrl(request, request.url.slice(0, hashIndex));
|
|
472
|
+
return attachRequestCfMetadata(new Request(stripped, { signal }), request);
|
|
473
|
+
}
|
|
446
474
|
//#endregion
|
|
447
|
-
export { INTERNAL_HEADERS, VINEXT_INTERNAL_HEADERS, attachRequestCfMetadata, canonicalizeRequestPathname, canonicalizeRequestUrlPathname, cloneRequestWithHeaders, cloneRequestWithUrl, createStaticFileSignal, dropEmptyMiddlewareSetCookie, filterInternalHeaders, getRepeatedSlashRedirect, guardProtocolRelativeUrl, hasBasePath, isOpenRedirectShaped, isOriginAllowed, normalizeTrailingSlash, normalizeTrailingSlashPathname, processMiddlewareHeaders, resolvePublicFileRoute, sendRepeatedSlashRedirect, stripBasePath, validateCsrfOrigin, validateServerActionPayload };
|
|
475
|
+
export { INTERNAL_HEADERS, VINEXT_INTERNAL_HEADERS, attachRequestCfMetadata, canonicalizeRequestPathname, canonicalizeRequestUrlPathname, cloneRequestWithHeaders, cloneRequestWithUrl, createStaticFileSignal, dropEmptyMiddlewareSetCookie, filterInternalHeaders, getRepeatedSlashRedirect, guardProtocolRelativeUrl, hasBasePath, haveSameHeaders, isOpenRedirectShaped, isOriginAllowed, normalizeTrailingSlash, normalizeTrailingSlashPathname, processMiddlewareHeaders, resolvePublicFileRoute, sendRepeatedSlashRedirect, stripBasePath, stripRequestUrlFragment, validateCsrfOrigin, validateServerActionPayload, withRequestHeaders };
|
|
@@ -88,9 +88,11 @@ function extractRscCompletionMetadata(buffer) {
|
|
|
88
88
|
}
|
|
89
89
|
function appendRscCompletionMetadata(source, getMetadata) {
|
|
90
90
|
const reader = source.getReader();
|
|
91
|
+
let cancelled = false;
|
|
91
92
|
return new ReadableStream({
|
|
92
93
|
async pull(controller) {
|
|
93
94
|
const next = await reader.read();
|
|
95
|
+
if (cancelled) return;
|
|
94
96
|
if (!next.done) {
|
|
95
97
|
controller.enqueue(escapeFlightChunk(next.value));
|
|
96
98
|
return;
|
|
@@ -100,6 +102,7 @@ function appendRscCompletionMetadata(source, getMetadata) {
|
|
|
100
102
|
controller.close();
|
|
101
103
|
},
|
|
102
104
|
cancel(reason) {
|
|
105
|
+
cancelled = true;
|
|
103
106
|
return reader.cancel(reason);
|
|
104
107
|
}
|
|
105
108
|
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { NextI18nConfig } from "../config/next-config.js";
|
|
2
|
+
//#region src/server/shared-cache-identity.d.ts
|
|
3
|
+
/** The core cache identity the configured adapter keys shared dispatches by, if any. */
|
|
4
|
+
export declare function adapterSharedCacheIdentity(): "host-free" | "query-free" | null;
|
|
5
|
+
/** Whether the configured adapter keys shared dispatches by a core cache identity. */
|
|
6
|
+
export declare function adapterUsesSharedCacheIdentity(): boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Whether a Pages page's response is one for every host, as Next.js serves a
|
|
9
|
+
* getStaticProps page and an automatically static page. A page without data
|
|
10
|
+
* functions is rendered per request when its getInitialProps or a custom
|
|
11
|
+
* _app's runs, and may read the host, so it keeps the host in its key.
|
|
12
|
+
*/
|
|
13
|
+
export declare function pagesPageSharesAcrossHosts(route: {
|
|
14
|
+
dataKind?: string;
|
|
15
|
+
runsInitialProps?: boolean;
|
|
16
|
+
} | null | undefined): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* The origin a shared Pages page identity names. A static Pages render reads
|
|
19
|
+
* the host only to select a configured i18n domain, so the identity keeps that
|
|
20
|
+
* domain, as vinext's Pages ISR key does, and every other host shares one entry.
|
|
21
|
+
*/
|
|
22
|
+
export declare function pagesCacheIdentityOrigin(requestUrl: string, i18nConfig: NextI18nConfig | null | undefined): string;
|
|
23
|
+
//#endregion
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { detectDomainLocale, normalizeDomainHostname } from "../utils/domain-locale.js";
|
|
2
|
+
import { getCdnCacheAdapter } from "../shims/cdn-cache.js";
|
|
3
|
+
import { VINEXT_CACHE_IDENTITY_ORIGIN } from "./multi-stage.js";
|
|
4
|
+
//#region src/server/shared-cache-identity.ts
|
|
5
|
+
/** The core cache identity the configured adapter keys shared dispatches by, if any. */
|
|
6
|
+
function adapterSharedCacheIdentity() {
|
|
7
|
+
const adapter = getCdnCacheAdapter();
|
|
8
|
+
if (adapter.requiresCompletedResponseAdmission !== true) return null;
|
|
9
|
+
return adapter.responseStageCacheIdentity ?? null;
|
|
10
|
+
}
|
|
11
|
+
/** Whether the configured adapter keys shared dispatches by a core cache identity. */
|
|
12
|
+
function adapterUsesSharedCacheIdentity() {
|
|
13
|
+
return adapterSharedCacheIdentity() !== null;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Whether a Pages page's response is one for every host, as Next.js serves a
|
|
17
|
+
* getStaticProps page and an automatically static page. A page without data
|
|
18
|
+
* functions is rendered per request when its getInitialProps or a custom
|
|
19
|
+
* _app's runs, and may read the host, so it keeps the host in its key.
|
|
20
|
+
*/
|
|
21
|
+
function pagesPageSharesAcrossHosts(route) {
|
|
22
|
+
if (route?.dataKind === "static") return true;
|
|
23
|
+
return route?.dataKind === "none" && route.runsInitialProps !== true;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* The origin a shared Pages page identity names. A static Pages render reads
|
|
27
|
+
* the host only to select a configured i18n domain, so the identity keeps that
|
|
28
|
+
* domain, as vinext's Pages ISR key does, and every other host shares one entry.
|
|
29
|
+
*/
|
|
30
|
+
function pagesCacheIdentityOrigin(requestUrl, i18nConfig) {
|
|
31
|
+
const domainLocale = detectDomainLocale(i18nConfig?.domains, new URL(requestUrl).hostname);
|
|
32
|
+
if (!domainLocale) return VINEXT_CACHE_IDENTITY_ORIGIN;
|
|
33
|
+
return `${domainLocale.http ? "http" : "https"}://${normalizeDomainHostname(domainLocale.domain)}`;
|
|
34
|
+
}
|
|
35
|
+
//#endregion
|
|
36
|
+
export { adapterSharedCacheIdentity, adapterUsesSharedCacheIdentity, pagesCacheIdentityOrigin, pagesPageSharesAcrossHosts };
|