vinext 1.0.0 → 1.1.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 +72 -1
- package/THIRD_PARTY_LICENSES.md +26 -0
- package/dist/build/app-page-static-eligibility.d.ts +15 -0
- package/dist/build/app-page-static-eligibility.js +82 -0
- package/dist/build/lifecycle.js +10 -10
- package/dist/build/pages-client-assets-module.js +6 -1
- package/dist/build/precompress.js +1 -1
- package/dist/build/prerender-paths.js +6 -85
- package/dist/build/prerender.d.ts +8 -1
- package/dist/build/prerender.js +167 -46
- package/dist/build/run-prerender.js +4 -3
- package/dist/build/server-entry.d.ts +2 -0
- package/dist/build/server-entry.js +7 -1
- package/dist/build/server-manifest.d.ts +7 -0
- package/dist/build/server-manifest.js +11 -1
- package/dist/cache/cache-adapters-virtual.d.ts +7 -1
- package/dist/cache/cache-adapters-virtual.js +3 -3
- package/dist/client/browser-globals.d.ts +4 -0
- package/dist/client/browser-globals.js +5 -0
- package/dist/client/navigation-runtime.d.ts +11 -1
- package/dist/client/navigation-runtime.js +3 -3
- package/dist/config/config-matchers.js +3 -1
- package/dist/config/dotenv.js +14 -3
- package/dist/config/next-config.d.ts +7 -0
- package/dist/config/next-config.js +18 -3
- package/dist/entries/app-rsc-entry.d.ts +2 -0
- package/dist/entries/app-rsc-entry.js +67 -45
- package/dist/index.d.ts +4 -1
- package/dist/index.js +200 -100
- package/dist/init-cloudflare.d.ts +1 -1
- package/dist/init-cloudflare.js +6 -6
- package/dist/init-platform.js +1 -1
- package/dist/init.js +4 -2
- 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/commonjs-syntax.d.ts +16 -0
- package/dist/plugins/commonjs-syntax.js +22 -0
- package/dist/plugins/fonts.d.ts +8 -11
- package/dist/plugins/fonts.js +71 -34
- package/dist/plugins/ignore-dynamic-requests.d.ts +11 -0
- package/dist/plugins/ignore-dynamic-requests.js +54 -3
- package/dist/plugins/import-meta-url.js +6 -6
- package/dist/plugins/og-asset-ownership.d.ts +2 -0
- package/dist/plugins/og-asset-ownership.js +24 -13
- package/dist/plugins/og-assets.d.ts +18 -0
- package/dist/plugins/og-assets.js +50 -8
- package/dist/plugins/og-harfbuzz.js +38 -27
- package/dist/plugins/optimize-imports.js +2 -1
- package/dist/plugins/require-context.d.ts +1 -0
- package/dist/plugins/require-context.js +28 -1
- package/dist/plugins/scan-build-css.d.ts +12 -0
- package/dist/plugins/scan-build-css.js +39 -0
- package/dist/plugins/strip-server-exports.d.ts +2 -0
- package/dist/plugins/strip-server-exports.js +3 -1
- package/dist/plugins/transform-result.d.ts +18 -0
- package/dist/plugins/transform-result.js +23 -2
- package/dist/plugins/typeof-window.d.ts +10 -0
- package/dist/plugins/typeof-window.js +33 -9
- package/dist/routing/app-route-graph.d.ts +0 -1
- package/dist/routing/app-route-graph.js +2 -4
- package/dist/routing/app-route-ids.d.ts +3 -0
- package/dist/routing/app-route-ids.js +6 -0
- package/dist/routing/file-matcher.d.ts +1 -0
- package/dist/routing/file-matcher.js +1 -1
- package/dist/server/api-handler.js +17 -7
- package/dist/server/app-bfcache-id.d.ts +1 -0
- package/dist/server/app-bfcache-id.js +7 -1
- package/dist/server/app-bfcache-identity.js +1 -2
- package/dist/server/app-browser-entry.js +15 -9
- 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-hydration.d.ts +1 -1
- package/dist/server/app-browser-hydration.js +2 -2
- 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-state.js +1 -1
- package/dist/server/app-browser-stream.d.ts +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 -1
- package/dist/server/app-history-state.js +9 -5
- package/dist/server/app-middleware.js +2 -1
- 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 +65 -44
- package/dist/server/app-page-cache.d.ts +5 -0
- package/dist/server/app-page-cache.js +27 -7
- package/dist/server/app-page-dispatch.d.ts +9 -1
- package/dist/server/app-page-dispatch.js +47 -30
- 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-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 +2 -2
- package/dist/server/app-page-render.d.ts +13 -5
- package/dist/server/app-page-render.js +219 -118
- package/dist/server/app-page-request.d.ts +0 -1
- package/dist/server/app-page-request.js +1 -2
- 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 +55 -33
- 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-search-params-observation.js +1 -1
- package/dist/server/app-page-stream.d.ts +15 -8
- package/dist/server/app-page-stream.js +7 -1
- package/dist/server/app-page-tracing.js +2 -1
- package/dist/server/app-pages-bridge.js +3 -2
- package/dist/server/app-render-abort-error.d.ts +3 -0
- package/dist/server/app-render-abort-error.js +8 -0
- package/dist/server/app-request-stage-dispatch.js +1 -1
- package/dist/server/app-request-stage-independent-entry.js +8 -11
- 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-route-handler-cache.d.ts +2 -1
- package/dist/server/app-route-handler-cache.js +11 -7
- package/dist/server/app-route-handler-dispatch.js +11 -4
- package/dist/server/app-route-handler-execution.d.ts +9 -1
- package/dist/server/app-route-handler-execution.js +28 -13
- package/dist/server/app-route-handler-policy.js +2 -2
- package/dist/server/app-route-handler-response.d.ts +1 -1
- package/dist/server/app-route-handler-response.js +14 -5
- package/dist/server/app-router-entry.d.ts +2 -1
- package/dist/server/app-router-entry.js +8 -12
- package/dist/server/app-rsc-errors.d.ts +0 -1
- package/dist/server/app-rsc-errors.js +2 -6
- package/dist/server/app-rsc-handler.d.ts +5 -0
- package/dist/server/app-rsc-handler.js +229 -102
- package/dist/server/app-rsc-request-normalization.d.ts +4 -2
- package/dist/server/app-rsc-request-normalization.js +7 -4
- package/dist/server/app-rsc-response-finalizer.js +4 -1
- package/dist/server/app-rsc-response-stage.d.ts +1 -1
- package/dist/server/app-rsc-response-stage.js +6 -4
- package/dist/server/app-rsc-route-matching.d.ts +9 -1
- package/dist/server/app-rsc-route-matching.js +37 -20
- package/dist/server/app-server-action-execution.d.ts +2 -1
- package/dist/server/app-server-action-execution.js +1 -1
- package/dist/server/app-ssr-entry.d.ts +3 -2
- package/dist/server/app-ssr-entry.js +9 -7
- package/dist/server/app-ssr-search-params-gate.js +1 -1
- package/dist/server/app-ssr-stream.d.ts +6 -1
- package/dist/server/app-ssr-stream.js +35 -16
- package/dist/server/app-worker-stages.d.ts +2 -2
- package/dist/server/app-worker-stages.js +3 -3
- package/dist/server/cache-control.js +3 -11
- package/dist/server/cacheability-request.js +56 -52
- package/dist/server/config-headers.js +3 -1
- package/dist/server/dev-server.js +23 -5
- package/dist/server/headers.d.ts +16 -0
- package/dist/server/headers.js +19 -1
- package/dist/server/http-error-responses.js +1 -0
- package/dist/server/image-optimization.d.ts +16 -0
- package/dist/server/image-optimization.js +26 -6
- package/dist/server/isr-cache.d.ts +2 -0
- package/dist/server/isr-cache.js +8 -3
- package/dist/server/metadata-route-response.js +94 -37
- package/dist/server/middleware-matcher-pattern.js +8 -4
- package/dist/server/middleware-response-headers.js +2 -0
- package/dist/server/multi-stage.d.ts +8 -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/open-redirect.d.ts +47 -0
- package/dist/server/open-redirect.js +74 -1
- package/dist/server/pages-api-route.js +8 -2
- package/dist/server/pages-asset-tags.d.ts +1 -0
- package/dist/server/pages-asset-tags.js +73 -22
- package/dist/server/pages-client-assets.d.ts +2 -0
- package/dist/server/pages-page-data.d.ts +6 -1
- package/dist/server/pages-page-data.js +71 -65
- package/dist/server/pages-page-handler.js +50 -15
- package/dist/server/pages-page-response.js +3 -1
- package/dist/server/pages-request-pipeline.d.ts +2 -1
- package/dist/server/pages-request-pipeline.js +20 -5
- package/dist/server/pages-request-stage-entry.js +14 -8
- package/dist/server/prerender-manifest.d.ts +6 -0
- package/dist/server/prerender-manifest.js +1 -1
- package/dist/server/prod-server.d.ts +8 -7
- package/dist/server/prod-server.js +152 -78
- package/dist/server/request-pipeline.d.ts +20 -8
- package/dist/server/request-pipeline.js +21 -7
- package/dist/server/response-compression.d.ts +43 -0
- package/dist/server/response-compression.js +111 -0
- package/dist/server/response-stage-cacheability.js +1 -1
- package/dist/server/seed-cache.js +10 -7
- package/dist/server/socket-error-backstop.d.ts +14 -0
- package/dist/server/socket-error-backstop.js +27 -4
- package/dist/server/worker-revalidation-context.d.ts +2 -1
- package/dist/server/worker-revalidation-context.js +1 -0
- package/dist/server/workers-tracing.d.ts +17 -0
- package/dist/server/workers-tracing.js +48 -8
- 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 +2 -40
- package/dist/shims/cache-callable-runtime.js +50 -168
- package/dist/shims/cache-flight-arguments.d.ts +22 -0
- package/dist/shims/cache-flight-arguments.js +56 -0
- package/dist/shims/cache-request-state.d.ts +18 -14
- package/dist/shims/cache-request-state.js +33 -21
- package/dist/shims/cache-runtime.d.ts +6 -19
- package/dist/shims/cache-runtime.js +168 -226
- package/dist/shims/cache.d.ts +3 -2
- package/dist/shims/cache.js +8 -5
- package/dist/shims/cacheability-classification.d.ts +8 -1
- package/dist/shims/cacheability-classification.js +2 -2
- package/dist/shims/cdn-cache.d.ts +10 -1
- package/dist/shims/cdn-cache.js +16 -9
- 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/error.d.ts +4 -18
- package/dist/shims/error.js +17 -10
- package/dist/shims/error.react-server.d.ts +4 -6
- package/dist/shims/error.react-server.js +4 -1
- package/dist/shims/fetch-cache.d.ts +6 -0
- package/dist/shims/fetch-cache.js +23 -4
- package/dist/shims/form.js +1 -1
- package/dist/shims/headers.d.ts +19 -69
- package/dist/shims/headers.js +82 -183
- 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/cache-context-accessor.d.ts +16 -0
- package/dist/shims/internal/cache-context-accessor.js +15 -0
- package/dist/shims/internal/headers-state.d.ts +73 -0
- package/dist/shims/internal/headers-state.js +157 -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 +16 -6
- package/dist/shims/request-context.d.ts +9 -0
- package/dist/shims/request-state-types.d.ts +2 -1
- package/dist/shims/root-params.js +1 -1
- package/dist/shims/server.js +52 -2
- 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/utils/encode-cache-tag.d.ts +1 -0
- package/dist/utils/encode-cache-tag.js +11 -1
- package/dist/utils/mdx-scan.d.ts +5 -0
- package/dist/utils/mdx-scan.js +8 -1
- package/dist/utils/regex-safety.d.ts +10 -0
- package/dist/utils/regex-safety.js +70 -18
- package/dist/utils/vite-cli-invocation.js +8 -1
- package/package.json +8 -4
- package/dist/server/metadata-route-cache-policy.d.ts +0 -5
- package/dist/server/metadata-route-cache-policy.js +0 -6
|
@@ -4,15 +4,16 @@ import { PRERENDER_REVALIDATE_HEADER, VINEXT_MW_CTX_HEADER, VINEXT_PRERENDER_ROU
|
|
|
4
4
|
import { hasMiddlewareRequestHeaderOverrides } from "../utils/middleware-request-headers.js";
|
|
5
5
|
import { requestContextFromRequest } from "../config/request-context.js";
|
|
6
6
|
import { isExternalUrl } from "../utils/external-url.js";
|
|
7
|
+
import { assetPrefixPathname, isNextStaticPath } from "../utils/asset-prefix.js";
|
|
7
8
|
import { normalizePathnameForRouteMatchStrict } from "../routing/utils.js";
|
|
8
9
|
import { addBasePathToPathname, hasBasePath, stripBasePath } from "../utils/base-path.js";
|
|
9
10
|
import { patternToNextFormat } from "../routing/route-validation.js";
|
|
10
11
|
import { getRequestExecutionContext } from "../shims/request-context.js";
|
|
11
12
|
import "./app-rsc-vary.js";
|
|
12
|
-
import { ACTION_REVALIDATED_HEADER, FLIGHT_HEADERS, VINEXT_PARAMS_HEADER, VINEXT_RENDERED_PATH_AND_SEARCH_HEADER } from "./headers.js";
|
|
13
|
+
import { ACTION_REVALIDATED_HEADER, FLIGHT_HEADERS, VINEXT_PARAMS_HEADER, VINEXT_PRERENDER_REWRITTEN_HEADER, VINEXT_RENDERED_PATH_AND_SEARCH_HEADER, VINEXT_SPECIAL_ERROR_STATUS_HEADER } from "./headers.js";
|
|
13
14
|
import { isInterceptionMatchedUrlPath, normalizePath } from "./normalize-path.js";
|
|
14
|
-
import { badRequestResponse, notFoundResponse } from "./http-error-responses.js";
|
|
15
|
-
import { cloneRequestWithHeaders, cloneRequestWithUrl, filterInternalHeaders, normalizeTrailingSlash, resolvePublicFileRoute } from "./request-pipeline.js";
|
|
15
|
+
import { badRequestResponse, notFoundResponse, notFoundStaticAssetResponse } from "./http-error-responses.js";
|
|
16
|
+
import { cloneRequestWithHeaders, cloneRequestWithUrl, filterInternalHeaders, normalizeTrailingSlash, normalizeTrailingSlashPathname, resolvePublicFileRoute } from "./request-pipeline.js";
|
|
16
17
|
import { normalizeDefaultLocalePathname } from "./pages-i18n.js";
|
|
17
18
|
import { getCdnCacheAdapter } from "../shims/cdn-cache.js";
|
|
18
19
|
import { markRouteCacheabilityDynamic, preserveRouteCacheabilityResponsePolicy } from "../shims/cacheability-classification.js";
|
|
@@ -36,6 +37,8 @@ import { setFrameworkRequestRoute, traceFrameworkRequest } from "./request-traci
|
|
|
36
37
|
import { matchPrerenderRouteParamsPayload, readTrustedPrerenderRouteParams, serializePrerenderRouteParamsHeader } from "./prerender-route-params.js";
|
|
37
38
|
import { buildPageCacheTags } from "./implicit-tags.js";
|
|
38
39
|
import { createServerActionNotFoundResponse, getServerActionNotFoundMessage } from "./server-action-not-found.js";
|
|
40
|
+
import { isPossibleAppRouteActionRequest } from "./app-action-request.js";
|
|
41
|
+
import { normalizeInterceptionContextHeader } from "./app-interception-context-header.js";
|
|
39
42
|
import { buildPostMwRequestContext } from "./app-post-middleware-context.js";
|
|
40
43
|
import { pickRootParams, setRootParams } from "../shims/root-params.js";
|
|
41
44
|
import { createRouteTreePrefetchResponse, isRouteTreePrefetchRequest } from "./app-route-tree-prefetch.js";
|
|
@@ -50,6 +53,33 @@ import { consumePagesResponseStagePolicyOwner, withoutResponseStageVary } from "
|
|
|
50
53
|
const HAS_CONFIG_HEADERS = process.env.__VINEXT_HAS_CONFIG_HEADERS !== "false";
|
|
51
54
|
const HAS_CONFIG_REDIRECTS = process.env.__VINEXT_HAS_CONFIG_REDIRECTS !== "false";
|
|
52
55
|
const HAS_CONFIG_REWRITES = process.env.__VINEXT_HAS_CONFIG_REWRITES !== "false";
|
|
56
|
+
/**
|
|
57
|
+
* Decode an interception context to the canonical source pathname it names.
|
|
58
|
+
* Throws for any value the client could not send back as its context header.
|
|
59
|
+
*/
|
|
60
|
+
function decodeInterceptionSourcePathname(context) {
|
|
61
|
+
if (!isInterceptionMatchedUrlPath(context)) throw new Error("Invalid interception source pathname");
|
|
62
|
+
if (new URL(context, "http://n").pathname !== context) throw new Error("Interception source is not a parsed URL pathname");
|
|
63
|
+
const decodedSourcePathname = normalizePathnameForRouteMatchStrict(context);
|
|
64
|
+
if (/[\t\n\r]/.test(decodedSourcePathname)) throw new Error("Interception source contains a stripped URL character");
|
|
65
|
+
if (hasUrlParserDotSegment(decodedSourcePathname)) throw new Error("Interception source contains a URL dot segment");
|
|
66
|
+
const sourcePathname = normalizePath(decodedSourcePathname);
|
|
67
|
+
if (sourcePathname !== decodedSourcePathname) throw new Error("Non-canonical interception source pathname");
|
|
68
|
+
return sourcePathname;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Whether a server-derived context satisfies the whole inbound header
|
|
72
|
+
* contract, so the client can send it back unchanged on its next request.
|
|
73
|
+
*/
|
|
74
|
+
function isValidInterceptionSourceContext(context) {
|
|
75
|
+
if (normalizeInterceptionContextHeader(context) !== context) return false;
|
|
76
|
+
try {
|
|
77
|
+
decodeInterceptionSourcePathname(context);
|
|
78
|
+
return true;
|
|
79
|
+
} catch {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
53
83
|
function ruleUsesUnkeyedRequestCondition(rule) {
|
|
54
84
|
return [...rule.has ?? [], ...rule.missing ?? []].some((condition) => condition.type === "header" || condition.type === "cookie" || condition.type === "host");
|
|
55
85
|
}
|
|
@@ -122,6 +152,26 @@ function applyMiddlewareContextToResponse(response, middlewareContext, appendToP
|
|
|
122
152
|
headers
|
|
123
153
|
}));
|
|
124
154
|
}
|
|
155
|
+
/**
|
|
156
|
+
* Next.js answers a Link's segment prefetch of a page whose notFound(),
|
|
157
|
+
* forbidden() or unauthorized() it stored with a 200, so its router renders
|
|
158
|
+
* the page's fallback without loading the document. A shared response stage
|
|
159
|
+
* gives that prefetch the navigation's response, so the request's own headers
|
|
160
|
+
* decide the status here.
|
|
161
|
+
*/
|
|
162
|
+
function withStoredSpecialErrorStatus(response, isSegmentPrefetch) {
|
|
163
|
+
const marker = response.headers.get(VINEXT_SPECIAL_ERROR_STATUS_HEADER);
|
|
164
|
+
if (marker === null) return response;
|
|
165
|
+
const headers = new Headers(response.headers);
|
|
166
|
+
headers.delete(VINEXT_SPECIAL_ERROR_STATUS_HEADER);
|
|
167
|
+
const storedStatus = Number(marker);
|
|
168
|
+
const status = !(storedStatus === 401 || storedStatus === 403 || storedStatus === 404) ? response.status : isSegmentPrefetch ? 200 : storedStatus;
|
|
169
|
+
return preserveFullyBufferedBodyMetadata(response, new Response(response.body, {
|
|
170
|
+
headers,
|
|
171
|
+
status,
|
|
172
|
+
statusText: status === response.status ? response.statusText : ""
|
|
173
|
+
}));
|
|
174
|
+
}
|
|
125
175
|
function hasProperty(value, key) {
|
|
126
176
|
return key in value;
|
|
127
177
|
}
|
|
@@ -205,7 +255,8 @@ function requestWithoutRscSuffix(request) {
|
|
|
205
255
|
url.pathname = pathname;
|
|
206
256
|
return cloneRequestWithUrl(request, url.toString());
|
|
207
257
|
}
|
|
208
|
-
|
|
258
|
+
/** Send a response with the never-cache policy, rebuilding immutable headers. */
|
|
259
|
+
function withNeverCacheControl(response) {
|
|
209
260
|
const applyNoStore = (headers) => {
|
|
210
261
|
applyCdnResponseHeaders(headers, { cacheControl: NEVER_CACHE_CONTROL });
|
|
211
262
|
};
|
|
@@ -223,6 +274,13 @@ function markUnverifiedInterceptionResponseUncacheable(response) {
|
|
|
223
274
|
}
|
|
224
275
|
return markedResponse;
|
|
225
276
|
}
|
|
277
|
+
const unmatchedRouteResponses = /* @__PURE__ */ new WeakSet();
|
|
278
|
+
/** Send an unmatched route's 404 with the never-cache policy, as Next.js does. */
|
|
279
|
+
function withUnmatchedRouteCacheControl(response) {
|
|
280
|
+
const markedResponse = withNeverCacheControl(response);
|
|
281
|
+
unmatchedRouteResponses.add(markedResponse);
|
|
282
|
+
return markedResponse;
|
|
283
|
+
}
|
|
226
284
|
async function handleAppRscRequest(options, request, preMiddlewareRequestContext, middlewareContext, isDataRequest, isMiddlewareDataRequest, pagesDataRequest, dispatchInternalRequest, allowInternalRscDocumentFallback, dispatchResponseStage, responseStageProbeMode = null, setInterceptionResponseUncacheable = () => {}) {
|
|
227
285
|
const handlerStart = process.env.NODE_ENV !== "production" ? performance.now() : 0;
|
|
228
286
|
if (process.env.NODE_ENV !== "production") {
|
|
@@ -236,7 +294,7 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
236
294
|
...options.configRewrites.fallback,
|
|
237
295
|
...options.configHeaders
|
|
238
296
|
].some((rule) => rule.basePath === false);
|
|
239
|
-
const normalized = normalizeRscRequest(request, options.basePath, canHandleOutsideBasePath);
|
|
297
|
+
const normalized = normalizeRscRequest(request, options.basePath, canHandleOutsideBasePath, options.assetPrefix);
|
|
240
298
|
if (normalized instanceof Response) {
|
|
241
299
|
if (request.headers.has("X-Vinext-Interception-Context") || request.headers.has("X-Vinext-Interception-Id")) setInterceptionResponseUncacheable(true);
|
|
242
300
|
return normalized;
|
|
@@ -247,12 +305,7 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
247
305
|
if (hasRawInterceptionContext) setInterceptionResponseUncacheable(true);
|
|
248
306
|
let interceptionSourcePathname = null;
|
|
249
307
|
if (isRscRequest && interceptionContextHeader !== null) try {
|
|
250
|
-
|
|
251
|
-
const decodedInterceptionSourcePathname = normalizePathnameForRouteMatchStrict(interceptionContextHeader);
|
|
252
|
-
if (/[\t\n\r]/.test(decodedInterceptionSourcePathname)) throw new Error("Interception source contains a stripped URL character");
|
|
253
|
-
if (hasUrlParserDotSegment(decodedInterceptionSourcePathname)) throw new Error("Interception source contains a URL dot segment");
|
|
254
|
-
interceptionSourcePathname = normalizePath(decodedInterceptionSourcePathname);
|
|
255
|
-
if (interceptionSourcePathname !== decodedInterceptionSourcePathname) throw new Error("Non-canonical interception source pathname");
|
|
308
|
+
interceptionSourcePathname = decodeInterceptionSourcePathname(interceptionContextHeader);
|
|
256
309
|
} catch {
|
|
257
310
|
options.clearRequestContext();
|
|
258
311
|
setInterceptionResponseUncacheable(true);
|
|
@@ -281,10 +334,10 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
281
334
|
});
|
|
282
335
|
if (selectorCacheBustingRedirect) return selectorCacheBustingRedirect;
|
|
283
336
|
}
|
|
284
|
-
const provesConcreteInterceptionSource = (sourceMatch) => {
|
|
337
|
+
const provesConcreteInterceptionSource = (sourceMatch, sourceContext = interceptionContextHeader) => {
|
|
285
338
|
if (sourceMatch === null) return false;
|
|
286
339
|
if (sourceMatch.interceptionSourceIsConcrete !== void 0) return sourceMatch.interceptionSourceIsConcrete;
|
|
287
|
-
return
|
|
340
|
+
return sourceContext !== null && (options.matchRequestRoute ?? options.matchRoute)(sourceContext)?.route === sourceMatch.route;
|
|
288
341
|
};
|
|
289
342
|
if (provesConcreteInterceptionSource(hadBasePath && hasRawInterceptionContext && interceptionContextHeader !== null ? options.matchInterceptRoute?.(requestCleanPathname, interceptionContextHeader, interceptionIdHeader) ?? null : null)) setInterceptionResponseUncacheable(false);
|
|
290
343
|
if (pathname === "/__vinext/prerender/static-params" || pathname === "/__vinext/prerender/pages-static-paths" || pathname === "/__vinext/prerender/metadata-routes") {
|
|
@@ -460,7 +513,7 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
460
513
|
isRscRequest,
|
|
461
514
|
middlewareCookieOverlay,
|
|
462
515
|
mountedSlotsHeader,
|
|
463
|
-
protocolVersion:
|
|
516
|
+
protocolVersion: 11,
|
|
464
517
|
requestOrigin: url.origin,
|
|
465
518
|
renderMode,
|
|
466
519
|
resolvedUrl,
|
|
@@ -617,8 +670,9 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
617
670
|
});
|
|
618
671
|
const directPreActionMatch = filesystemRouteEligible ? matchCleanPathname() : null;
|
|
619
672
|
const preActionRoutePathname = cleanPathnameIsRequestPathname ? requestCleanPathname : cleanPathname;
|
|
620
|
-
|
|
621
|
-
|
|
673
|
+
let interceptionSourceContext = interceptionContextHeader;
|
|
674
|
+
let interceptionSourceMatch = filesystemRouteEligible && interceptionSourcePathname !== null && interceptionContextHeader !== null ? options.matchInterceptRoute?.(preActionRoutePathname, interceptionContextHeader, interceptionIdHeader) ?? null : null;
|
|
675
|
+
let hasVerifiedInterceptionSource = provesConcreteInterceptionSource(interceptionSourceMatch);
|
|
622
676
|
if (interceptionIdHeader !== null && !hasVerifiedInterceptionSource) {
|
|
623
677
|
options.clearRequestContext();
|
|
624
678
|
setInterceptionResponseUncacheable(true);
|
|
@@ -633,81 +687,142 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
633
687
|
bypassInterceptionContextCache = true;
|
|
634
688
|
setInterceptionResponseUncacheable(true);
|
|
635
689
|
};
|
|
636
|
-
if (interceptionSourceMatch !== null &&
|
|
637
|
-
const
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
const targetHeadersContext = getHeadersContext();
|
|
645
|
-
const targetRequestHeaders = targetHeadersContext ? new Headers(targetHeadersContext.headers) : null;
|
|
646
|
-
targetRequestHeaders?.delete(VINEXT_MW_CTX_HEADER);
|
|
647
|
-
for (const header of FLIGHT_HEADERS) targetRequestHeaders?.delete(header);
|
|
648
|
-
if (targetRequestHeaders) {
|
|
649
|
-
const sourceHeaderNames = Array.from(sourceMiddlewareRequest.headers.keys());
|
|
650
|
-
for (const header of sourceHeaderNames) sourceMiddlewareRequest.headers.delete(header);
|
|
651
|
-
for (const [name, value] of targetRequestHeaders) sourceMiddlewareRequest.headers.append(name, value);
|
|
652
|
-
}
|
|
653
|
-
const sourceMiddlewareContext = {
|
|
654
|
-
headers: null,
|
|
655
|
-
requestHeaders: null,
|
|
656
|
-
status: null
|
|
657
|
-
};
|
|
658
|
-
const sourceHeadersContext = headersContextFromRequest(sourceMiddlewareRequest, { draftModeSecret: options.draftModeSecret });
|
|
659
|
-
let sourceMiddlewareResult;
|
|
660
|
-
try {
|
|
661
|
-
sourceMiddlewareResult = await runWithHeadersContext(sourceHeadersContext, () => runMiddleware({
|
|
662
|
-
cleanPathname: interceptionSourcePathname,
|
|
663
|
-
context: sourceMiddlewareContext,
|
|
664
|
-
externalRewriteRequest: normalizedUserlandRequest,
|
|
665
|
-
hadBasePath,
|
|
666
|
-
isDataRequest: isMiddlewareDataRequest,
|
|
667
|
-
request: sourceMiddlewareRequest,
|
|
668
|
-
validateExternalRewriteRequest: () => validateClaimedOutsideBasePathRsc(true)
|
|
669
|
-
}));
|
|
670
|
-
} finally {
|
|
671
|
-
if (sourceMiddlewareRequest.body && !sourceMiddlewareRequest.bodyUsed && !sourceMiddlewareRequest.body.locked) sourceMiddlewareRequest.body.cancel().catch(() => {});
|
|
672
|
-
if (sourceRequest !== userlandRequest && sourceRequest.body && !sourceRequest.bodyUsed && !sourceRequest.body.locked) sourceRequest.body.cancel().catch(() => {});
|
|
673
|
-
}
|
|
674
|
-
if (!dispatchResponseStage && sourceMiddlewareResult.pathnameEligible) markRouteCacheabilityDynamic(sourceMiddlewareResult.matched ? "middleware matched this request" : "middleware is eligible for this pathname");
|
|
675
|
-
if (sourceMiddlewareResult.kind === "response") {
|
|
676
|
-
options.clearRequestContext();
|
|
677
|
-
return sourceMiddlewareResult.response;
|
|
678
|
-
}
|
|
679
|
-
let sourceHeadersCompatible = true;
|
|
680
|
-
if (targetRequestHeaders) {
|
|
681
|
-
for (const [name, value] of targetRequestHeaders) if (sourceHeadersContext.headers.get(name) !== value) {
|
|
682
|
-
sourceHeadersCompatible = false;
|
|
683
|
-
break;
|
|
690
|
+
if (interceptionSourceMatch !== null && interceptionContextHeader !== null && interceptionSourcePathname !== null && !(interceptionSourceMatch.route === directPreActionMatch?.route && haveSamePageParams(interceptionSourceMatch.params, directPreActionMatch.params))) {
|
|
691
|
+
const sourceRequestPathname = normalizeTrailingSlashPathname(interceptionContextHeader, options.trailingSlash) ?? interceptionContextHeader;
|
|
692
|
+
const decodedSourceRequestPathname = normalizeTrailingSlashPathname(interceptionSourcePathname, options.trailingSlash) ?? interceptionSourcePathname;
|
|
693
|
+
const adoptRewrittenInterceptionSource = (rewrittenPathname) => {
|
|
694
|
+
const rewrittenInterceptionSourceMatch = isValidInterceptionSourceContext(rewrittenPathname) ? options.matchInterceptRoute?.(preActionRoutePathname, rewrittenPathname, interceptionIdHeader) ?? null : null;
|
|
695
|
+
if (rewrittenInterceptionSourceMatch !== null) {
|
|
696
|
+
interceptionSourceMatch = rewrittenInterceptionSourceMatch;
|
|
697
|
+
interceptionSourceContext = rewrittenPathname;
|
|
684
698
|
}
|
|
685
|
-
|
|
686
|
-
|
|
699
|
+
const rewrittenSourceMatch = options.matchRoute(rewrittenPathname);
|
|
700
|
+
return interceptionSourceMatch !== null && rewrittenSourceMatch?.route === interceptionSourceMatch.route && haveSamePageParams(rewrittenSourceMatch.params, interceptionSourceMatch.params);
|
|
701
|
+
};
|
|
702
|
+
if (configMatchers?.matchRedirect(matchPathname(sourceRequestPathname), options.configRedirects, preMiddlewareRequestContext, basePathState, dispatchResponseStage ? void 0 : markConditionalRedirectCacheability)) {
|
|
687
703
|
options.clearRequestContext();
|
|
688
704
|
return notFoundResponse();
|
|
689
705
|
}
|
|
690
|
-
let
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
706
|
+
let sourceRulesPathname = sourceRequestPathname;
|
|
707
|
+
if (runMiddleware) {
|
|
708
|
+
const sourceUrl = new URL(userlandRequest.url);
|
|
709
|
+
sourceUrl.search = new URL(resolvedUrl, url).search;
|
|
710
|
+
const sourceUrlPathname = hadBasePath && options.basePath ? sourceRequestPathname === "/" ? options.basePath : options.basePath + sourceRequestPathname : sourceRequestPathname;
|
|
711
|
+
sourceUrl.pathname = sourceUrlPathname;
|
|
712
|
+
if (sourceUrl.pathname !== sourceUrlPathname) {
|
|
713
|
+
options.clearRequestContext();
|
|
714
|
+
setInterceptionResponseUncacheable(true);
|
|
715
|
+
return badRequestResponse();
|
|
716
|
+
}
|
|
717
|
+
const sourceRequest = userlandRequest.body ? userlandRequest.clone() : userlandRequest;
|
|
718
|
+
const sourceMiddlewareRequest = cloneRequestWithUrl(sourceRequest, sourceUrl.href);
|
|
719
|
+
sourceMiddlewareRequest.headers.delete(VINEXT_MW_CTX_HEADER);
|
|
720
|
+
for (const header of FLIGHT_HEADERS) sourceMiddlewareRequest.headers.delete(header);
|
|
721
|
+
const targetHeadersContext = getHeadersContext();
|
|
722
|
+
const targetRequestHeaders = targetHeadersContext ? new Headers(targetHeadersContext.headers) : null;
|
|
723
|
+
targetRequestHeaders?.delete(VINEXT_MW_CTX_HEADER);
|
|
724
|
+
for (const header of FLIGHT_HEADERS) targetRequestHeaders?.delete(header);
|
|
725
|
+
if (targetRequestHeaders) {
|
|
726
|
+
const sourceHeaderNames = Array.from(sourceMiddlewareRequest.headers.keys());
|
|
727
|
+
for (const header of sourceHeaderNames) sourceMiddlewareRequest.headers.delete(header);
|
|
728
|
+
for (const [name, value] of targetRequestHeaders) sourceMiddlewareRequest.headers.append(name, value);
|
|
729
|
+
}
|
|
730
|
+
const sourceMiddlewareContext = {
|
|
731
|
+
headers: null,
|
|
732
|
+
requestHeaders: null,
|
|
733
|
+
status: null
|
|
734
|
+
};
|
|
735
|
+
const sourceHeadersContext = headersContextFromRequest(sourceMiddlewareRequest, { draftModeSecret: options.draftModeSecret });
|
|
736
|
+
let sourceMiddlewareResult;
|
|
737
|
+
try {
|
|
738
|
+
sourceMiddlewareResult = await runWithHeadersContext(sourceHeadersContext, () => runMiddleware({
|
|
739
|
+
cleanPathname: decodedSourceRequestPathname,
|
|
740
|
+
context: sourceMiddlewareContext,
|
|
741
|
+
externalRewriteRequest: normalizedUserlandRequest,
|
|
742
|
+
hadBasePath,
|
|
743
|
+
isDataRequest: isMiddlewareDataRequest,
|
|
744
|
+
request: sourceMiddlewareRequest,
|
|
745
|
+
validateExternalRewriteRequest: () => validateClaimedOutsideBasePathRsc(true)
|
|
746
|
+
}));
|
|
747
|
+
} finally {
|
|
748
|
+
if (sourceMiddlewareRequest.body && !sourceMiddlewareRequest.bodyUsed && !sourceMiddlewareRequest.body.locked) sourceMiddlewareRequest.body.cancel().catch(() => {});
|
|
749
|
+
if (sourceRequest !== userlandRequest && sourceRequest.body && !sourceRequest.bodyUsed && !sourceRequest.body.locked) sourceRequest.body.cancel().catch(() => {});
|
|
750
|
+
}
|
|
751
|
+
if (!dispatchResponseStage && sourceMiddlewareResult.pathnameEligible) markRouteCacheabilityDynamic(sourceMiddlewareResult.matched ? "middleware matched this request" : "middleware is eligible for this pathname");
|
|
752
|
+
if (sourceMiddlewareResult.kind === "response") {
|
|
753
|
+
options.clearRequestContext();
|
|
754
|
+
return sourceMiddlewareResult.response;
|
|
755
|
+
}
|
|
756
|
+
let sourceHeadersCompatible = true;
|
|
757
|
+
if (targetRequestHeaders) {
|
|
758
|
+
for (const [name, value] of targetRequestHeaders) if (sourceHeadersContext.headers.get(name) !== value) {
|
|
759
|
+
sourceHeadersCompatible = false;
|
|
760
|
+
break;
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
if (!targetHeadersContext || !targetRequestHeaders || !sourceHeadersCompatible || !haveSameRequestCookies(targetHeadersContext.cookies, sourceHeadersContext.cookies)) {
|
|
764
|
+
options.clearRequestContext();
|
|
765
|
+
return notFoundResponse();
|
|
766
|
+
}
|
|
767
|
+
let addedSourceHeader = false;
|
|
768
|
+
for (const [name, value] of sourceHeadersContext.headers) if (!targetRequestHeaders.has(name)) {
|
|
769
|
+
targetHeadersContext.headers.set(name, value);
|
|
770
|
+
addedSourceHeader = true;
|
|
771
|
+
}
|
|
772
|
+
if (addedSourceHeader) {
|
|
773
|
+
targetHeadersContext.readonlyHeaders = void 0;
|
|
774
|
+
canUseSharedWorkerResponseStage = false;
|
|
775
|
+
}
|
|
776
|
+
if (sourceMiddlewareResult.rewritten) {
|
|
777
|
+
if (sourceMiddlewareResult.search !== sourceUrl.search || !adoptRewrittenInterceptionSource(sourceMiddlewareResult.cleanPathname)) {
|
|
778
|
+
options.clearRequestContext();
|
|
779
|
+
return notFoundResponse();
|
|
780
|
+
}
|
|
781
|
+
sourceRulesPathname = sourceMiddlewareResult.cleanPathname;
|
|
782
|
+
}
|
|
698
783
|
}
|
|
699
|
-
if (
|
|
700
|
-
const
|
|
701
|
-
|
|
784
|
+
if (HAS_CONFIG_REWRITES && options.configRewrites.beforeFiles.length) {
|
|
785
|
+
const { matchRewrite } = await import("../config/config-matchers.js");
|
|
786
|
+
const sourceRewriteContext = requestContextForResolvedUrl(buildPostMwRequestContext(userlandRequest), resolvedUrl, url);
|
|
787
|
+
let didRewriteSource = false;
|
|
788
|
+
for (const rewrite of options.configRewrites.beforeFiles) {
|
|
789
|
+
const destination = matchRewrite(matchPathname(sourceRulesPathname), [rewrite], sourceRewriteContext, basePathState, matchPathname(sourceRulesPathname), dispatchResponseStage === void 0 ? markConditionalRewriteCacheability : void 0);
|
|
790
|
+
if (!destination) continue;
|
|
791
|
+
if (isExternalUrl(destination) || destination.includes("?")) {
|
|
792
|
+
options.clearRequestContext();
|
|
793
|
+
return notFoundResponse();
|
|
794
|
+
}
|
|
795
|
+
sourceRulesPathname = pathnameForResolvedUrl(destination);
|
|
796
|
+
didRewriteSource = true;
|
|
797
|
+
}
|
|
798
|
+
if (didRewriteSource && !adoptRewrittenInterceptionSource(sourceRulesPathname)) {
|
|
702
799
|
options.clearRequestContext();
|
|
703
800
|
return notFoundResponse();
|
|
704
801
|
}
|
|
705
802
|
}
|
|
706
803
|
}
|
|
804
|
+
if (interceptionSourceMatch !== null) {
|
|
805
|
+
hasVerifiedInterceptionSource = provesConcreteInterceptionSource(interceptionSourceMatch, interceptionSourceContext);
|
|
806
|
+
if (!hasVerifiedInterceptionSource) {
|
|
807
|
+
if (interceptionIdHeader !== null) {
|
|
808
|
+
options.clearRequestContext();
|
|
809
|
+
setInterceptionResponseUncacheable(true);
|
|
810
|
+
return badRequestResponse();
|
|
811
|
+
}
|
|
812
|
+
interceptionSourceMatch = null;
|
|
813
|
+
interceptionSourceContext = null;
|
|
814
|
+
}
|
|
815
|
+
bypassInterceptionContextCache = hasRawInterceptionContext && !hasVerifiedInterceptionSource;
|
|
816
|
+
setInterceptionResponseUncacheable(bypassInterceptionContextCache);
|
|
817
|
+
}
|
|
707
818
|
const interceptionPreActionMatch = filesystemRouteEligible && directPreActionMatch === null && isRscRequest && interceptionSourcePathname !== null ? interceptionSourceMatch : null;
|
|
708
819
|
const preActionMatch = directPreActionMatch ?? interceptionPreActionMatch;
|
|
709
820
|
const isInterceptionMatch = interceptionPreActionMatch !== null;
|
|
710
|
-
|
|
821
|
+
const rendersRawRequestMatch = options.matchRawRequestRoute !== void 0 && (isPossibleAppRouteActionRequest(request) || isDraftModeRequest(request, options.draftModeSecret) || isDraftModeEnabled());
|
|
822
|
+
const usesRawRequestMatch = () => rendersRawRequestMatch && cleanPathnameIsRequestPathname && !isInterceptionMatch;
|
|
823
|
+
const renderedRouteMatch = (routeMatch) => routeMatch !== null && usesRawRequestMatch() ? options.matchRawRequestRoute(requestCleanPathname) ?? routeMatch : routeMatch;
|
|
824
|
+
const renderedPreActionMatch = renderedRouteMatch(preActionMatch);
|
|
825
|
+
if (renderedPreActionMatch) setRootParams(pickRootParams(renderedPreActionMatch.params, renderedPreActionMatch.route.rootParamNames));
|
|
711
826
|
if (pagesDataRequest && didMiddlewareRewritePathname && preActionMatch && !preActionMatch.route.isDynamic) {
|
|
712
827
|
const headers = new Headers();
|
|
713
828
|
mergeMiddlewareResponseHeaders(headers, middlewareContext.headers);
|
|
@@ -728,7 +843,7 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
728
843
|
contentType,
|
|
729
844
|
middlewareContext,
|
|
730
845
|
request,
|
|
731
|
-
routeMatch:
|
|
846
|
+
routeMatch: renderedPreActionMatch
|
|
732
847
|
});
|
|
733
848
|
else if (preActionMatch?.route.__loadPage && !preActionMatch.route.__loadRouteHandler) return createMissingServerActionResponse(options, null);
|
|
734
849
|
}
|
|
@@ -760,13 +875,13 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
760
875
|
actionId,
|
|
761
876
|
cleanPathname,
|
|
762
877
|
contentType,
|
|
763
|
-
interceptionContext:
|
|
878
|
+
interceptionContext: interceptionSourceContext,
|
|
764
879
|
isRscRequest,
|
|
765
880
|
middlewareContext,
|
|
766
881
|
mountedSlotsHeader,
|
|
767
882
|
request,
|
|
768
883
|
scriptNonce,
|
|
769
|
-
routeMatch:
|
|
884
|
+
routeMatch: renderedPreActionMatch,
|
|
770
885
|
routePathname: preActionRoutePathname,
|
|
771
886
|
dispatchRedirectTargetRequest: dispatchInternalRequest,
|
|
772
887
|
sourceConfigHeaders,
|
|
@@ -802,7 +917,7 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
802
917
|
matchKind,
|
|
803
918
|
middlewareCookieOverlay,
|
|
804
919
|
preHandlerHeaders: cache === "shared" && resourceKind === "page" && dataKind === "static" ? null : [...await loadPreHandlerResponseHeaders()],
|
|
805
|
-
protocolVersion:
|
|
920
|
+
protocolVersion: 11,
|
|
806
921
|
requestOrigin: url.origin,
|
|
807
922
|
resourceKind,
|
|
808
923
|
requestUrl: request.url,
|
|
@@ -837,15 +952,18 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
837
952
|
if (response) preserveRouteCacheabilityResponsePolicy();
|
|
838
953
|
if (!response) return null;
|
|
839
954
|
if (sharedOuterPolicyNeedsReconciliation) reconcileCdnResponseHeadersAfterOuterPolicy(response.headers, await loadOuterResponsePolicy());
|
|
840
|
-
|
|
955
|
+
const isRewritten = resolvedUrl !== originalResolvedUrl;
|
|
956
|
+
const isPrerender = typeof process !== "undefined" && process.env?.VINEXT_PRERENDER === "1";
|
|
957
|
+
if ((!pagesDataRequest || !isRewritten) && !isPrerender) return dispatchPagesResponseStage ? markAppRscResponseConfigHeadersApplied(response) : response;
|
|
841
958
|
const headers = new Headers(response.headers);
|
|
842
|
-
headers.set("x-nextjs-rewrite", resolvedUrl);
|
|
843
|
-
|
|
959
|
+
if (pagesDataRequest && isRewritten) headers.set("x-nextjs-rewrite", resolvedUrl);
|
|
960
|
+
if (isPrerender) headers.set(VINEXT_PRERENDER_REWRITTEN_HEADER, isRewritten ? "1" : "0");
|
|
961
|
+
const markedResponse = new Response(response.body, {
|
|
844
962
|
headers,
|
|
845
963
|
status: response.status,
|
|
846
964
|
statusText: response.statusText
|
|
847
965
|
});
|
|
848
|
-
return dispatchPagesResponseStage ? markAppRscResponseConfigHeadersApplied(
|
|
966
|
+
return dispatchPagesResponseStage ? markAppRscResponseConfigHeadersApplied(markedResponse) : markedResponse;
|
|
849
967
|
};
|
|
850
968
|
const staticPagesFallbackResponse = await renderPagesForMatchKind("static");
|
|
851
969
|
if (staticPagesFallbackResponse) {
|
|
@@ -931,23 +1049,31 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
931
1049
|
}
|
|
932
1050
|
if (match) break;
|
|
933
1051
|
}
|
|
934
|
-
if (interceptionCacheProofInvalidated &&
|
|
1052
|
+
if (interceptionCacheProofInvalidated && interceptionSourceContext !== null) {
|
|
935
1053
|
const finalInterceptionTargetPathname = cleanPathnameIsRequestPathname ? requestCleanPathname : cleanPathname;
|
|
936
|
-
const finalInterceptionSourceMatch = filesystemRouteEligible && match !== null ? options.matchInterceptRoute?.(finalInterceptionTargetPathname,
|
|
1054
|
+
const finalInterceptionSourceMatch = filesystemRouteEligible && match !== null ? options.matchInterceptRoute?.(finalInterceptionTargetPathname, interceptionSourceContext, interceptionIdHeader) ?? null : null;
|
|
937
1055
|
const hasVerifiedFinalInterceptionSource = hasVerifiedInterceptionSource && interceptionSourceMatch !== null && provesConcreteInterceptionSource(finalInterceptionSourceMatch) && finalInterceptionSourceMatch?.route === interceptionSourceMatch.route && haveSamePageParams(finalInterceptionSourceMatch.params, interceptionSourceMatch.params);
|
|
938
1056
|
if (interceptionIdHeader !== null && !hasVerifiedFinalInterceptionSource) {
|
|
939
1057
|
options.clearRequestContext();
|
|
940
1058
|
setInterceptionResponseUncacheable(true);
|
|
941
1059
|
return badRequestResponse();
|
|
942
1060
|
}
|
|
1061
|
+
if (!hasVerifiedFinalInterceptionSource) interceptionSourceContext = null;
|
|
943
1062
|
bypassInterceptionContextCache = !hasVerifiedFinalInterceptionSource;
|
|
944
1063
|
setInterceptionResponseUncacheable(bypassInterceptionContextCache);
|
|
945
1064
|
}
|
|
1065
|
+
if ((!filesystemRouteEligible || !match) && isNextStaticPath(cleanPathname, "", assetPrefixPathname(options.assetPrefix ?? ""))) {
|
|
1066
|
+
options.clearRequestContext();
|
|
1067
|
+
const headers = new Headers();
|
|
1068
|
+
mergeMiddlewareResponseHeaders(headers, middlewareContext.headers);
|
|
1069
|
+
applyCdnResponseHeaders(headers, { cacheControl: NEVER_CACHE_CONTROL });
|
|
1070
|
+
return notFoundStaticAssetResponse(headers);
|
|
1071
|
+
}
|
|
946
1072
|
if (!filesystemRouteEligible) {
|
|
947
1073
|
options.clearRequestContext();
|
|
948
1074
|
const headers = new Headers();
|
|
949
1075
|
mergeMiddlewareResponseHeaders(headers, middlewareContext.headers);
|
|
950
|
-
return notFoundResponse({ headers });
|
|
1076
|
+
return withUnmatchedRouteCacheControl(notFoundResponse({ headers }));
|
|
951
1077
|
}
|
|
952
1078
|
if (pagesDataRequest) {
|
|
953
1079
|
options.clearRequestContext();
|
|
@@ -971,7 +1097,7 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
971
1097
|
}
|
|
972
1098
|
setFrameworkRequestRoute("/404", isRscRequest);
|
|
973
1099
|
const notFoundResponseStage = transportedResponseStage ?? options.renderResponseStageLocally;
|
|
974
|
-
if (notFoundResponseStage) return composeResponseStageResponse(await notFoundResponseStage(responseStageRequest(), {
|
|
1100
|
+
if (notFoundResponseStage) return withUnmatchedRouteCacheControl(await composeResponseStageResponse(await notFoundResponseStage(responseStageRequest(), {
|
|
975
1101
|
kind: "app-not-found",
|
|
976
1102
|
buildId: options.buildId,
|
|
977
1103
|
cacheability: responseStageCacheability(resolvedUrl),
|
|
@@ -981,12 +1107,12 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
981
1107
|
isRscRequest,
|
|
982
1108
|
middlewareCookieOverlay,
|
|
983
1109
|
mountedSlotsHeader,
|
|
984
|
-
protocolVersion:
|
|
1110
|
+
protocolVersion: 11,
|
|
985
1111
|
requestOrigin: url.origin,
|
|
986
1112
|
renderMode,
|
|
987
1113
|
resolvedUrl,
|
|
988
1114
|
scriptNonce: scriptNonce ?? null
|
|
989
|
-
}));
|
|
1115
|
+
})));
|
|
990
1116
|
const renderedNotFoundResponse = await traceAppPageRender("/404", "render", () => options.renderNotFound({
|
|
991
1117
|
isRscRequest,
|
|
992
1118
|
middlewareContext,
|
|
@@ -994,12 +1120,13 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
994
1120
|
route: null,
|
|
995
1121
|
scriptNonce
|
|
996
1122
|
}));
|
|
997
|
-
if (renderedNotFoundResponse) return renderedNotFoundResponse;
|
|
1123
|
+
if (renderedNotFoundResponse) return withUnmatchedRouteCacheControl(renderedNotFoundResponse);
|
|
998
1124
|
options.clearRequestContext();
|
|
999
1125
|
const headers = new Headers();
|
|
1000
1126
|
mergeMiddlewareResponseHeaders(headers, middlewareContext.headers);
|
|
1001
|
-
return notFoundResponse({ headers });
|
|
1127
|
+
return withUnmatchedRouteCacheControl(notFoundResponse({ headers }));
|
|
1002
1128
|
}
|
|
1129
|
+
match = renderedRouteMatch(match);
|
|
1003
1130
|
const { route, params } = match;
|
|
1004
1131
|
const requestPathnameDiffersFromCachePath = requestCleanPathname !== cleanPathname;
|
|
1005
1132
|
const rawRequestPathnameIsObservable = isInterceptionMatch || route.routeHandler != null || typeof route.__loadRouteHandler === "function";
|
|
@@ -1027,7 +1154,7 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
1027
1154
|
const prerenderRouteParams = prerenderRouteParamsMatch?.params ?? null;
|
|
1028
1155
|
const isPrerenderFallbackShell = prerenderRouteParamsMatch?.kind === "fallback-shell";
|
|
1029
1156
|
const renderParams = prerenderRouteParams ?? params;
|
|
1030
|
-
const responseStageMatchKind = isInterceptionMatch ? "interception" : cleanPathnameIsRequestPathname && options.matchRequestRoute ? "request" : "resolved";
|
|
1157
|
+
const responseStageMatchKind = isInterceptionMatch ? "interception" : cleanPathnameIsRequestPathname && options.matchRequestRoute ? usesRawRequestMatch() ? "raw-request" : "request" : "resolved";
|
|
1031
1158
|
const responseStageRoutePathname = isInterceptionMatch ? preActionRoutePathname : cleanPathnameIsRequestPathname ? requestCleanPathname || "/" : cleanPathname || "/";
|
|
1032
1159
|
const matchedResponseStage = transportedResponseStage ?? options.renderResponseStageLocally;
|
|
1033
1160
|
let runtimeFallbackShells = [];
|
|
@@ -1067,7 +1194,7 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
1067
1194
|
middlewareCookieOverlay,
|
|
1068
1195
|
mountedSlotsHeader,
|
|
1069
1196
|
params,
|
|
1070
|
-
protocolVersion:
|
|
1197
|
+
protocolVersion: 11,
|
|
1071
1198
|
requestOrigin: url.origin,
|
|
1072
1199
|
renderMode,
|
|
1073
1200
|
resolvedUrl,
|
|
@@ -1088,7 +1215,7 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
1088
1215
|
searchParams: resolvedSearchParams
|
|
1089
1216
|
});
|
|
1090
1217
|
}
|
|
1091
|
-
const pageResponse = matchedResponseStage ? await matchedResponseStage(responseStageRequest(), {
|
|
1218
|
+
const pageResponse = withStoredSpecialErrorStatus(matchedResponseStage ? await matchedResponseStage(responseStageRequest(), {
|
|
1092
1219
|
kind: "app-page",
|
|
1093
1220
|
buildId: options.buildId,
|
|
1094
1221
|
cacheability: responseStageCacheability(resolvedUrl),
|
|
@@ -1099,14 +1226,14 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
1099
1226
|
cleanPathname,
|
|
1100
1227
|
draftModeCookie,
|
|
1101
1228
|
forceDynamic: route.forceDynamic === true,
|
|
1102
|
-
interceptionContext: isRscRequest ?
|
|
1229
|
+
interceptionContext: isRscRequest ? interceptionSourceContext : null,
|
|
1103
1230
|
interceptionId: interceptionIdHeader,
|
|
1104
1231
|
isRscRequest,
|
|
1105
1232
|
matchKind: responseStageMatchKind,
|
|
1106
1233
|
middlewareCookieOverlay,
|
|
1107
1234
|
mountedSlotsHeader,
|
|
1108
1235
|
params,
|
|
1109
|
-
protocolVersion:
|
|
1236
|
+
protocolVersion: 11,
|
|
1110
1237
|
requestOrigin: url.origin,
|
|
1111
1238
|
renderMode,
|
|
1112
1239
|
resolvedUrl,
|
|
@@ -1123,7 +1250,7 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
1123
1250
|
actionError: normalizedProgressiveActionError,
|
|
1124
1251
|
actionFailed,
|
|
1125
1252
|
handlerStart,
|
|
1126
|
-
interceptionContext: isRscRequest ?
|
|
1253
|
+
interceptionContext: isRscRequest ? interceptionSourceContext : null,
|
|
1127
1254
|
interceptionId: interceptionIdHeader,
|
|
1128
1255
|
interceptionPathname: cleanPathnameIsRequestPathname ? requestCleanPathname : cleanPathname,
|
|
1129
1256
|
isProgressiveActionRender,
|
|
@@ -1146,7 +1273,7 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
1146
1273
|
scriptNonce,
|
|
1147
1274
|
searchParams: resolvedSearchParams,
|
|
1148
1275
|
renderMode
|
|
1149
|
-
});
|
|
1276
|
+
}), isRscRequest && request.headers.get("Next-Router-Prefetch") === "1" && request.headers.has("Next-Router-Segment-Prefetch"));
|
|
1150
1277
|
if (isProgressiveActionRender) return applyProgressiveActionSideEffects(pageResponse, progressiveActionFormState);
|
|
1151
1278
|
return pageResponse;
|
|
1152
1279
|
}
|
|
@@ -1250,7 +1377,7 @@ function createAppRscRequestHandler(options) {
|
|
|
1250
1377
|
recordCacheability: dispatchResponseStage === void 0,
|
|
1251
1378
|
requestContext: preMiddlewareRequestContext
|
|
1252
1379
|
});
|
|
1253
|
-
return interceptionResponseUncacheable ?
|
|
1380
|
+
return interceptionResponseUncacheable || unmatchedRouteResponses.has(response) ? withNeverCacheControl(response) : response;
|
|
1254
1381
|
}, {
|
|
1255
1382
|
cacheComponents: options.createPprFallbackShells !== void 0,
|
|
1256
1383
|
route: () => new URL(request.url).pathname
|
|
@@ -35,7 +35,9 @@ export type NormalizedRscRequest = {
|
|
|
35
35
|
*
|
|
36
36
|
* 1. Parse URL
|
|
37
37
|
* 2. Protocol-relative URL guard — on the raw pathname, BEFORE normalizePath collapses
|
|
38
|
-
* `//` to `/`.
|
|
38
|
+
* `//` to `/`. Literal repeated slashes / backslashes get Next.js's 308 to the
|
|
39
|
+
* collapsed path; encoded leading `%2F` / `%5C` get a 404. If the guard ran after
|
|
40
|
+
* normalization, `//evil.com` → `/evil.com`
|
|
39
41
|
* would bypass the check and reach the trailing-slash redirector, which echoes the
|
|
40
42
|
* path into a `Location` header that browsers interpret as protocol-relative.
|
|
41
43
|
* 3. Strict percent-decode each segment — throws on malformed sequences (→ 400). Must
|
|
@@ -55,6 +57,6 @@ export type NormalizedRscRequest = {
|
|
|
55
57
|
* @returns A 400 or 404 Response for invalid or out-of-scope inputs,
|
|
56
58
|
* or a NormalizedRscRequest for valid requests.
|
|
57
59
|
*/
|
|
58
|
-
export declare function normalizeRscRequest(request: Request, basePath: string, allowOutsideBasePath?: boolean): Response | NormalizedRscRequest;
|
|
60
|
+
export declare function normalizeRscRequest(request: Request, basePath: string, allowOutsideBasePath?: boolean, assetPrefix?: string): Response | NormalizedRscRequest;
|
|
59
61
|
//#endregion
|
|
60
62
|
export { normalizeMountedSlotsHeader };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { assetPrefixPathname, isNextStaticPath } from "../utils/asset-prefix.js";
|
|
1
2
|
import { normalizePathnameForRouteMatchStrict } from "../routing/utils.js";
|
|
2
3
|
import { hasBasePath, stripBasePath } from "../utils/base-path.js";
|
|
3
4
|
import { NEXT_ROUTER_STATE_TREE_HEADER, NEXT_URL_HEADER, VINEXT_INTERCEPTION_CONTEXT_HEADER, VINEXT_INTERCEPTION_ID_HEADER, VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_RSC_RENDER_MODE_HEADER } from "./app-rsc-vary.js";
|
|
@@ -68,7 +69,9 @@ function tryNormalizeComparablePathAndSearch(value, basePath, baseUrl) {
|
|
|
68
69
|
*
|
|
69
70
|
* 1. Parse URL
|
|
70
71
|
* 2. Protocol-relative URL guard — on the raw pathname, BEFORE normalizePath collapses
|
|
71
|
-
* `//` to `/`.
|
|
72
|
+
* `//` to `/`. Literal repeated slashes / backslashes get Next.js's 308 to the
|
|
73
|
+
* collapsed path; encoded leading `%2F` / `%5C` get a 404. If the guard ran after
|
|
74
|
+
* normalization, `//evil.com` → `/evil.com`
|
|
72
75
|
* would bypass the check and reach the trailing-slash redirector, which echoes the
|
|
73
76
|
* path into a `Location` header that browsers interpret as protocol-relative.
|
|
74
77
|
* 3. Strict percent-decode each segment — throws on malformed sequences (→ 400). Must
|
|
@@ -88,9 +91,9 @@ function tryNormalizeComparablePathAndSearch(value, basePath, baseUrl) {
|
|
|
88
91
|
* @returns A 400 or 404 Response for invalid or out-of-scope inputs,
|
|
89
92
|
* or a NormalizedRscRequest for valid requests.
|
|
90
93
|
*/
|
|
91
|
-
function normalizeRscRequest(request, basePath, allowOutsideBasePath = false) {
|
|
94
|
+
function normalizeRscRequest(request, basePath, allowOutsideBasePath = false, assetPrefix = "") {
|
|
92
95
|
const url = new URL(request.url);
|
|
93
|
-
const protoGuard = guardProtocolRelativeUrl(url.pathname);
|
|
96
|
+
const protoGuard = guardProtocolRelativeUrl(url.pathname, url.search);
|
|
94
97
|
if (protoGuard) return protoGuard;
|
|
95
98
|
let decoded;
|
|
96
99
|
try {
|
|
@@ -103,7 +106,7 @@ function normalizeRscRequest(request, basePath, allowOutsideBasePath = false) {
|
|
|
103
106
|
let hadBasePath = true;
|
|
104
107
|
if (basePath) {
|
|
105
108
|
hadBasePath = hasBasePath(requestPathname, basePath);
|
|
106
|
-
if (!hadBasePath && !pathname.startsWith("/__vinext/") && !allowOutsideBasePath) return notFoundResponse();
|
|
109
|
+
if (!hadBasePath && !pathname.startsWith("/__vinext/") && !allowOutsideBasePath && !isNextStaticPath(pathname, "", assetPrefixPathname(assetPrefix))) return notFoundResponse();
|
|
107
110
|
if (hadBasePath) {
|
|
108
111
|
pathname = stripBasePath(pathname, basePath);
|
|
109
112
|
requestPathname = stripBasePath(requestPathname, basePath);
|
|
@@ -15,7 +15,10 @@ const configHeadersAlreadyApplied = /* @__PURE__ */ new WeakSet();
|
|
|
15
15
|
function normalizeExplicitNonCacheablePolicy(headers) {
|
|
16
16
|
if (!hasExplicitNonCacheableResponsePolicy(headers)) return;
|
|
17
17
|
const cacheControl = headers.get("Cache-Control");
|
|
18
|
-
applyCdnResponseHeaders(headers, {
|
|
18
|
+
applyCdnResponseHeaders(headers, {
|
|
19
|
+
cacheControl: cacheControl && isNonCacheableCacheControl(cacheControl) ? cacheControl : NO_STORE_CACHE_CONTROL,
|
|
20
|
+
browserCacheControl: cacheControl ?? void 0
|
|
21
|
+
});
|
|
19
22
|
}
|
|
20
23
|
/** Mark a response whose final target pipeline has already applied config headers. */
|
|
21
24
|
function markAppRscResponseConfigHeadersApplied(response) {
|