vinext 0.0.47 → 0.0.49
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 +1 -1
- package/dist/build/layout-classification.js +3 -1
- package/dist/build/layout-classification.js.map +1 -1
- package/dist/build/prerender.js +10 -10
- package/dist/build/prerender.js.map +1 -1
- package/dist/build/report.d.ts +8 -4
- package/dist/build/report.js +17 -7
- package/dist/build/report.js.map +1 -1
- package/dist/build/run-prerender.d.ts +5 -0
- package/dist/build/run-prerender.js +4 -1
- package/dist/build/run-prerender.js.map +1 -1
- package/dist/build/server-manifest.js +2 -7
- package/dist/build/server-manifest.js.map +1 -1
- package/dist/build/standalone.js +3 -5
- package/dist/build/standalone.js.map +1 -1
- package/dist/check.js +45 -29
- package/dist/check.js.map +1 -1
- package/dist/cli-args.d.ts +3 -1
- package/dist/cli-args.js +18 -1
- package/dist/cli-args.js.map +1 -1
- package/dist/cli.js +9 -1
- package/dist/cli.js.map +1 -1
- package/dist/config/config-matchers.js +46 -37
- package/dist/config/config-matchers.js.map +1 -1
- package/dist/deploy.d.ts +18 -2
- package/dist/deploy.js +47 -4
- package/dist/deploy.js.map +1 -1
- package/dist/entries/app-rsc-entry.js +11 -9
- package/dist/entries/app-rsc-entry.js.map +1 -1
- package/dist/entries/app-rsc-manifest.js +4 -1
- package/dist/entries/app-rsc-manifest.js.map +1 -1
- package/dist/entries/pages-client-entry.js +3 -2
- package/dist/entries/pages-client-entry.js.map +1 -1
- package/dist/entries/pages-server-entry.js +21 -62
- package/dist/entries/pages-server-entry.js.map +1 -1
- package/dist/entries/runtime-entry-module.d.ts +12 -3
- package/dist/entries/runtime-entry-module.js +15 -4
- package/dist/entries/runtime-entry-module.js.map +1 -1
- package/dist/index.js +12 -7
- package/dist/index.js.map +1 -1
- package/dist/init.d.ts +1 -1
- package/dist/init.js +2 -2
- package/dist/init.js.map +1 -1
- package/dist/plugins/og-assets.js +15 -16
- package/dist/plugins/og-assets.js.map +1 -1
- package/dist/plugins/rsc-client-shim-excludes.d.ts +2 -1
- package/dist/plugins/rsc-client-shim-excludes.js +10 -1
- package/dist/plugins/rsc-client-shim-excludes.js.map +1 -1
- package/dist/routing/app-route-graph.d.ts +90 -4
- package/dist/routing/app-route-graph.js +210 -7
- package/dist/routing/app-route-graph.js.map +1 -1
- package/dist/routing/app-router.d.ts +15 -3
- package/dist/routing/app-router.js +20 -23
- package/dist/routing/app-router.js.map +1 -1
- package/dist/routing/file-matcher.d.ts +3 -1
- package/dist/routing/file-matcher.js +6 -1
- package/dist/routing/file-matcher.js.map +1 -1
- package/dist/routing/pages-router.js +10 -19
- package/dist/routing/pages-router.js.map +1 -1
- package/dist/routing/route-matching.d.ts +28 -0
- package/dist/routing/route-matching.js +44 -0
- package/dist/routing/route-matching.js.map +1 -0
- package/dist/routing/route-pattern.js +4 -1
- package/dist/routing/route-pattern.js.map +1 -1
- package/dist/routing/route-trie.d.ts +8 -0
- package/dist/routing/route-trie.js +12 -1
- package/dist/routing/route-trie.js.map +1 -1
- package/dist/routing/route-validation.js +3 -4
- package/dist/routing/route-validation.js.map +1 -1
- package/dist/routing/utils.d.ts +8 -1
- package/dist/routing/utils.js +25 -2
- package/dist/routing/utils.js.map +1 -1
- package/dist/server/api-handler.js +2 -8
- package/dist/server/api-handler.js.map +1 -1
- package/dist/server/app-browser-entry.js +66 -49
- package/dist/server/app-browser-entry.js.map +1 -1
- package/dist/server/app-browser-navigation-controller.d.ts +7 -5
- package/dist/server/app-browser-navigation-controller.js +43 -35
- package/dist/server/app-browser-navigation-controller.js.map +1 -1
- package/dist/server/app-browser-state.d.ts +33 -15
- package/dist/server/app-browser-state.js +52 -59
- package/dist/server/app-browser-state.js.map +1 -1
- package/dist/server/app-browser-visible-commit.d.ts +68 -0
- package/dist/server/app-browser-visible-commit.js +182 -0
- package/dist/server/app-browser-visible-commit.js.map +1 -0
- package/dist/server/app-client-reference-preloader.d.ts +15 -0
- package/dist/server/app-client-reference-preloader.js +46 -0
- package/dist/server/app-client-reference-preloader.js.map +1 -0
- package/dist/server/app-elements-wire.d.ts +130 -0
- package/dist/server/app-elements-wire.js +205 -0
- package/dist/server/app-elements-wire.js.map +1 -0
- package/dist/server/app-elements.d.ts +2 -84
- package/dist/server/app-elements.js +3 -102
- package/dist/server/app-elements.js.map +1 -1
- package/dist/server/app-fallback-renderer.d.ts +1 -1
- package/dist/server/app-middleware.d.ts +2 -1
- package/dist/server/app-middleware.js +34 -11
- package/dist/server/app-middleware.js.map +1 -1
- package/dist/server/app-page-boundary-render.d.ts +1 -1
- package/dist/server/app-page-boundary-render.js +8 -5
- package/dist/server/app-page-boundary-render.js.map +1 -1
- package/dist/server/app-page-boundary.js +2 -1
- package/dist/server/app-page-boundary.js.map +1 -1
- package/dist/server/app-page-cache.d.ts +1 -0
- package/dist/server/app-page-cache.js +8 -13
- package/dist/server/app-page-cache.js.map +1 -1
- package/dist/server/app-page-dispatch.d.ts +2 -1
- package/dist/server/app-page-dispatch.js +18 -10
- package/dist/server/app-page-dispatch.js.map +1 -1
- package/dist/server/app-page-element-builder.d.ts +1 -1
- package/dist/server/app-page-element-builder.js +8 -5
- package/dist/server/app-page-element-builder.js.map +1 -1
- package/dist/server/app-page-execution.d.ts +23 -5
- package/dist/server/app-page-execution.js +39 -24
- package/dist/server/app-page-execution.js.map +1 -1
- package/dist/server/app-page-head.js +2 -1
- package/dist/server/app-page-head.js.map +1 -1
- package/dist/server/app-page-method.js +2 -5
- package/dist/server/app-page-method.js.map +1 -1
- package/dist/server/app-page-probe.d.ts +1 -1
- package/dist/server/app-page-probe.js +5 -1
- package/dist/server/app-page-probe.js.map +1 -1
- package/dist/server/app-page-render.d.ts +1 -1
- package/dist/server/app-page-render.js +38 -3
- package/dist/server/app-page-render.js.map +1 -1
- package/dist/server/app-page-request.d.ts +0 -1
- package/dist/server/app-page-request.js +7 -10
- package/dist/server/app-page-request.js.map +1 -1
- package/dist/server/app-page-response.js +3 -2
- package/dist/server/app-page-response.js.map +1 -1
- package/dist/server/app-page-route-wiring.d.ts +5 -2
- package/dist/server/app-page-route-wiring.js +15 -12
- package/dist/server/app-page-route-wiring.js.map +1 -1
- package/dist/server/app-page-stream.d.ts +7 -0
- package/dist/server/app-page-stream.js +9 -2
- package/dist/server/app-page-stream.js.map +1 -1
- package/dist/server/app-prerender-endpoints.js +3 -2
- package/dist/server/app-prerender-endpoints.js.map +1 -1
- package/dist/server/app-route-handler-cache.js +2 -1
- package/dist/server/app-route-handler-cache.js.map +1 -1
- package/dist/server/app-route-handler-dispatch.js +6 -5
- package/dist/server/app-route-handler-dispatch.js.map +1 -1
- package/dist/server/app-route-handler-policy.js +13 -13
- package/dist/server/app-route-handler-policy.js.map +1 -1
- package/dist/server/app-route-handler-response.js +2 -1
- package/dist/server/app-route-handler-response.js.map +1 -1
- package/dist/server/app-route-handler-runtime.d.ts +9 -1
- package/dist/server/app-route-handler-runtime.js +11 -1
- package/dist/server/app-route-handler-runtime.js.map +1 -1
- package/dist/server/app-router-entry.js +9 -4
- package/dist/server/app-router-entry.js.map +1 -1
- package/dist/server/app-rsc-cache-busting.d.ts +34 -0
- package/dist/server/app-rsc-cache-busting.js +137 -0
- package/dist/server/app-rsc-cache-busting.js.map +1 -0
- package/dist/server/app-rsc-handler.js +22 -11
- package/dist/server/app-rsc-handler.js.map +1 -1
- package/dist/server/app-rsc-request-normalization.d.ts +4 -2
- package/dist/server/app-rsc-request-normalization.js +10 -6
- package/dist/server/app-rsc-request-normalization.js.map +1 -1
- package/dist/server/app-rsc-response-finalizer.js +1 -1
- package/dist/server/app-rsc-route-matching.js +8 -4
- package/dist/server/app-rsc-route-matching.js.map +1 -1
- package/dist/server/app-segment-config.js +4 -0
- package/dist/server/app-segment-config.js.map +1 -1
- package/dist/server/app-server-action-execution.js +43 -51
- package/dist/server/app-server-action-execution.js.map +1 -1
- package/dist/server/app-ssr-entry.js +21 -20
- package/dist/server/app-ssr-entry.js.map +1 -1
- package/dist/server/artifact-compatibility.d.ts +44 -0
- package/dist/server/artifact-compatibility.js +82 -0
- package/dist/server/artifact-compatibility.js.map +1 -0
- package/dist/server/cache-proof.d.ts +200 -0
- package/dist/server/cache-proof.js +342 -0
- package/dist/server/cache-proof.js.map +1 -0
- package/dist/server/dev-origin-check.js +8 -4
- package/dist/server/dev-origin-check.js.map +1 -1
- package/dist/server/dev-server.js +6 -16
- package/dist/server/dev-server.js.map +1 -1
- package/dist/server/http-error-responses.d.ts +67 -0
- package/dist/server/http-error-responses.js +77 -0
- package/dist/server/http-error-responses.js.map +1 -0
- package/dist/server/image-optimization.js +2 -1
- package/dist/server/image-optimization.js.map +1 -1
- package/dist/server/metadata-route-response.js +6 -5
- package/dist/server/metadata-route-response.js.map +1 -1
- package/dist/server/metadata-routes.d.ts +1 -0
- package/dist/server/metadata-routes.js +6 -0
- package/dist/server/metadata-routes.js.map +1 -1
- package/dist/server/middleware-matcher.js +2 -2
- package/dist/server/middleware-matcher.js.map +1 -1
- package/dist/server/middleware-response-headers.js +21 -0
- package/dist/server/middleware-response-headers.js.map +1 -1
- package/dist/server/middleware-runtime.js +3 -3
- package/dist/server/middleware-runtime.js.map +1 -1
- package/dist/server/navigation-trace.d.ts +33 -0
- package/dist/server/navigation-trace.js +35 -0
- package/dist/server/navigation-trace.js.map +1 -0
- package/dist/server/next-error-digest.d.ts +44 -0
- package/dist/server/next-error-digest.js +40 -0
- package/dist/server/next-error-digest.js.map +1 -0
- package/dist/server/pages-api-route.js +4 -7
- package/dist/server/pages-api-route.js.map +1 -1
- package/dist/server/pages-node-compat.js +4 -16
- package/dist/server/pages-node-compat.js.map +1 -1
- package/dist/server/pages-page-response.d.ts +2 -8
- package/dist/server/pages-page-response.js +44 -14
- package/dist/server/pages-page-response.js.map +1 -1
- package/dist/server/prod-server.d.ts +6 -0
- package/dist/server/prod-server.js +28 -21
- package/dist/server/prod-server.js.map +1 -1
- package/dist/server/request-pipeline.d.ts +42 -1
- package/dist/server/request-pipeline.js +97 -17
- package/dist/server/request-pipeline.js.map +1 -1
- package/dist/shims/cache-runtime.d.ts +2 -2
- package/dist/shims/cache-runtime.js +3 -6
- package/dist/shims/cache-runtime.js.map +1 -1
- package/dist/shims/cache.js +3 -5
- package/dist/shims/cache.js.map +1 -1
- package/dist/shims/fetch-cache.js +2 -3
- package/dist/shims/fetch-cache.js.map +1 -1
- package/dist/shims/head-state.js +2 -3
- package/dist/shims/head-state.js.map +1 -1
- package/dist/shims/headers.js +4 -44
- package/dist/shims/headers.js.map +1 -1
- package/dist/shims/i18n-state.js +2 -3
- package/dist/shims/i18n-state.js.map +1 -1
- package/dist/shims/internal/als-registry.d.ts +15 -0
- package/dist/shims/internal/als-registry.js +55 -0
- package/dist/shims/internal/als-registry.js.map +1 -0
- package/dist/shims/internal/cookie-serialize.d.ts +46 -0
- package/dist/shims/internal/cookie-serialize.js +51 -0
- package/dist/shims/internal/cookie-serialize.js.map +1 -0
- package/dist/shims/link.js +31 -26
- package/dist/shims/link.js.map +1 -1
- package/dist/shims/metadata.d.ts +26 -1
- package/dist/shims/metadata.js +94 -4
- package/dist/shims/metadata.js.map +1 -1
- package/dist/shims/navigation-state.js +2 -3
- package/dist/shims/navigation-state.js.map +1 -1
- package/dist/shims/navigation.d.ts +2 -7
- package/dist/shims/navigation.js +44 -36
- package/dist/shims/navigation.js.map +1 -1
- package/dist/shims/request-context.js +2 -4
- package/dist/shims/request-context.js.map +1 -1
- package/dist/shims/router-state.js +2 -3
- package/dist/shims/router-state.js.map +1 -1
- package/dist/shims/router.js +2 -2
- package/dist/shims/router.js.map +1 -1
- package/dist/shims/server.js +5 -30
- package/dist/shims/server.js.map +1 -1
- package/dist/shims/slot.d.ts +1 -1
- package/dist/shims/slot.js +5 -4
- package/dist/shims/slot.js.map +1 -1
- package/dist/shims/thenable-params.d.ts +5 -2
- package/dist/shims/thenable-params.js +26 -6
- package/dist/shims/thenable-params.js.map +1 -1
- package/dist/shims/unified-request-context.js +2 -14
- package/dist/shims/unified-request-context.js.map +1 -1
- package/dist/utils/base-path.d.ts +7 -1
- package/dist/utils/base-path.js +12 -1
- package/dist/utils/base-path.js.map +1 -1
- package/dist/utils/query.d.ts +8 -1
- package/dist/utils/query.js +12 -1
- package/dist/utils/query.js.map +1 -1
- package/dist/utils/safe-json-file.d.ts +18 -0
- package/dist/utils/safe-json-file.js +25 -0
- package/dist/utils/safe-json-file.js.map +1 -0
- package/dist/utils/text-stream.d.ts +29 -0
- package/dist/utils/text-stream.js +66 -0
- package/dist/utils/text-stream.js.map +1 -0
- package/package.json +5 -5
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import { createRequestContext, runWithRequestContext } from "../shims/unified-request-context.js";
|
|
2
|
+
import { hasBasePath } from "../utils/base-path.js";
|
|
2
3
|
import { getRequestExecutionContext } from "../shims/request-context.js";
|
|
3
4
|
import { isExternalUrl, matchRedirect, matchRewrite, proxyExternalRequest, requestContextFromRequest, sanitizeDestination } from "../config/config-matchers.js";
|
|
4
|
-
import {
|
|
5
|
-
import { normalizeTrailingSlash, resolvePublicFileRoute, validateImageUrl } from "./request-pipeline.js";
|
|
5
|
+
import { notFoundResponse } from "./http-error-responses.js";
|
|
6
|
+
import { cloneRequestWithHeaders, filterInternalHeaders, normalizeTrailingSlash, resolvePublicFileRoute, validateImageUrl } from "./request-pipeline.js";
|
|
6
7
|
import { headersContextFromRequest } from "../shims/headers.js";
|
|
7
8
|
import { ensureFetchPatch, setCurrentFetchSoftTags } from "../shims/fetch-cache.js";
|
|
9
|
+
import { createRscRedirectLocation, resolveInvalidRscCacheBustingRequest, stripRscCacheBustingSearchParam, stripRscSuffix } from "./app-rsc-cache-busting.js";
|
|
8
10
|
import { getScriptNonceFromHeaderSources } from "./csp.js";
|
|
9
11
|
import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
|
|
10
12
|
import { applyAppMiddleware } from "./app-middleware.js";
|
|
13
|
+
import "./app-page-response.js";
|
|
11
14
|
import { buildPageCacheTags } from "./implicit-tags.js";
|
|
12
15
|
import { buildPostMwRequestContext } from "./app-post-middleware-context.js";
|
|
13
16
|
import { pickRootParams, setRootParams } from "../shims/root-params.js";
|
|
@@ -61,14 +64,20 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
61
64
|
if (prerenderEndpointResponse) return prerenderEndpointResponse;
|
|
62
65
|
const trailingSlashRedirect = normalizeTrailingSlash(pathname, options.basePath, options.trailingSlash, url.search);
|
|
63
66
|
if (trailingSlashRedirect) return trailingSlashRedirect;
|
|
64
|
-
const redirect = matchRedirect(
|
|
67
|
+
const redirect = matchRedirect(stripRscSuffix(pathname), options.configRedirects, preMiddlewareRequestContext);
|
|
65
68
|
if (redirect) {
|
|
66
69
|
const destination = sanitizeDestination(redirectDestinationWithBasePath(redirect.destination, options.basePath));
|
|
70
|
+
const location = isRscRequest && request.headers.get("RSC") === "1" ? await createRscRedirectLocation(destination, request) : destination;
|
|
67
71
|
return new Response(null, {
|
|
68
72
|
status: redirect.permanent ? 308 : 307,
|
|
69
|
-
headers: { Location:
|
|
73
|
+
headers: { Location: location }
|
|
70
74
|
});
|
|
71
75
|
}
|
|
76
|
+
const rscCacheBustingRedirect = await resolveInvalidRscCacheBustingRequest({
|
|
77
|
+
isRscRequest,
|
|
78
|
+
request
|
|
79
|
+
});
|
|
80
|
+
if (rscCacheBustingRedirect) return rscCacheBustingRedirect;
|
|
72
81
|
const middlewareContext = {
|
|
73
82
|
headers: null,
|
|
74
83
|
requestHeaders: null,
|
|
@@ -120,6 +129,7 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
120
129
|
options.clearRequestContext();
|
|
121
130
|
return publicFileResponse;
|
|
122
131
|
}
|
|
132
|
+
if (isRscRequest) stripRscCacheBustingSearchParam(url);
|
|
123
133
|
options.setNavigationContext({
|
|
124
134
|
pathname: cleanPathname,
|
|
125
135
|
searchParams: url.searchParams,
|
|
@@ -180,21 +190,18 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
180
190
|
options.clearRequestContext();
|
|
181
191
|
return pagesFallbackResponse;
|
|
182
192
|
}
|
|
183
|
-
const
|
|
193
|
+
const renderedNotFoundResponse = await options.renderNotFound({
|
|
184
194
|
isRscRequest,
|
|
185
195
|
middlewareContext,
|
|
186
196
|
request,
|
|
187
197
|
route: null,
|
|
188
198
|
scriptNonce
|
|
189
199
|
});
|
|
190
|
-
if (
|
|
200
|
+
if (renderedNotFoundResponse) return renderedNotFoundResponse;
|
|
191
201
|
options.clearRequestContext();
|
|
192
202
|
const headers = new Headers();
|
|
193
203
|
mergeMiddlewareResponseHeaders(headers, middlewareContext.headers);
|
|
194
|
-
return
|
|
195
|
-
status: 404,
|
|
196
|
-
headers
|
|
197
|
-
});
|
|
204
|
+
return notFoundResponse({ headers });
|
|
198
205
|
}
|
|
199
206
|
const { route, params } = match;
|
|
200
207
|
options.setNavigationContext({
|
|
@@ -229,8 +236,12 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
229
236
|
});
|
|
230
237
|
}
|
|
231
238
|
function createAppRscHandler(options) {
|
|
232
|
-
return async function appRscHandler(
|
|
239
|
+
return async function appRscHandler(rawRequest, ctx) {
|
|
233
240
|
await options.ensureInstrumentation?.();
|
|
241
|
+
const mwCtx = rawRequest.headers.get("x-vinext-mw-ctx");
|
|
242
|
+
const filteredHeaders = filterInternalHeaders(rawRequest.headers);
|
|
243
|
+
if (mwCtx !== null) filteredHeaders.set("x-vinext-mw-ctx", mwCtx);
|
|
244
|
+
const request = cloneRequestWithHeaders(rawRequest, filteredHeaders);
|
|
234
245
|
const executionContext = isExecutionContextLike(ctx) ? ctx : getRequestExecutionContext() ?? null;
|
|
235
246
|
return runWithRequestContext(createRequestContext({
|
|
236
247
|
headersContext: headersContextFromRequest(request),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-rsc-handler.js","names":[],"sources":["../../src/server/app-rsc-handler.ts"],"sourcesContent":["import type {\n NextHeader,\n NextI18nConfig,\n NextRedirect,\n NextRewrite,\n} from \"../config/next-config.js\";\nimport {\n isExternalUrl,\n matchRedirect,\n matchRewrite,\n proxyExternalRequest,\n requestContextFromRequest,\n sanitizeDestination,\n} from \"../config/config-matchers.js\";\nimport { headersContextFromRequest } from \"vinext/shims/headers\";\nimport { ensureFetchPatch, setCurrentFetchSoftTags } from \"vinext/shims/fetch-cache\";\nimport {\n getRequestExecutionContext,\n type ExecutionContextLike,\n} from \"vinext/shims/request-context\";\nimport { pickRootParams, setRootParams } from \"vinext/shims/root-params\";\nimport { createRequestContext, runWithRequestContext } from \"vinext/shims/unified-request-context\";\nimport { flattenErrorCauses } from \"../utils/error-cause.js\";\nimport { hasBasePath } from \"../utils/base-path.js\";\nimport { applyAppMiddleware, type AppMiddlewareContext } from \"./app-middleware.js\";\nimport { mergeMiddlewareResponseHeaders } from \"./app-page-response.js\";\nimport { handleAppPrerenderEndpoint } from \"./app-prerender-endpoints.js\";\nimport { finalizeAppRscResponse } from \"./app-rsc-response-finalizer.js\";\nimport { normalizeRscRequest } from \"./app-rsc-request-normalization.js\";\nimport { getScriptNonceFromHeaderSources } from \"./csp.js\";\nimport { buildPageCacheTags } from \"./implicit-tags.js\";\nimport { handleMetadataRouteRequest } from \"./metadata-route-response.js\";\nimport type { MiddlewareModule } from \"./middleware-runtime.js\";\nimport { runWithPrerenderWorkUnit } from \"./prerender-work-unit-setup.js\";\nimport { buildPostMwRequestContext } from \"./app-post-middleware-context.js\";\nimport {\n normalizeTrailingSlash,\n resolvePublicFileRoute,\n validateImageUrl,\n} from \"./request-pipeline.js\";\n\ntype AppPageParams = Record<string, string | string[]>;\ntype RequestContext = ReturnType<typeof requestContextFromRequest>;\ntype MetadataRoutes = Parameters<typeof handleMetadataRouteRequest>[0][\"metadataRoutes\"];\ntype MakeThenableParams = Parameters<typeof handleMetadataRouteRequest>[0][\"makeThenableParams\"];\ntype StaticParamsMap = Parameters<typeof handleAppPrerenderEndpoint>[1][\"staticParamsMap\"];\ntype RootParamNamesMap = Parameters<\n typeof handleAppPrerenderEndpoint\n>[1][\"rootParamNamesByPattern\"];\n\ntype AppRscMiddlewareContext = AppMiddlewareContext;\n\ntype AppRscHandlerRoute = {\n page?: unknown;\n pattern: string;\n rootParamNames?: readonly string[];\n routeHandler?: unknown;\n routeSegments: readonly string[];\n};\n\ntype AppRscRouteMatch<TRoute> = {\n params: AppPageParams;\n route: TRoute;\n};\n\ntype DispatchMatchedPageOptions<TRoute> = {\n cleanPathname: string;\n handlerStart: number;\n interceptionContext: string | null;\n isRscRequest: boolean;\n middlewareContext: AppRscMiddlewareContext;\n mountedSlotsHeader: string | null;\n params: AppPageParams;\n request: Request;\n route: TRoute;\n scriptNonce?: string;\n searchParams: URLSearchParams;\n};\n\ntype DispatchMatchedRouteHandlerOptions<TRoute> = {\n cleanPathname: string;\n middlewareContext: AppRscMiddlewareContext;\n params: AppPageParams;\n request: Request;\n route: TRoute;\n searchParams: URLSearchParams;\n};\n\ntype HandleProgressiveActionRequestOptions = {\n actionId: string | null;\n cleanPathname: string;\n contentType: string;\n middlewareContext: AppRscMiddlewareContext;\n request: Request;\n};\n\ntype HandleServerActionRequestOptions = {\n actionId: string | null;\n cleanPathname: string;\n contentType: string;\n interceptionContext: string | null;\n isRscRequest: boolean;\n middlewareContext: AppRscMiddlewareContext;\n mountedSlotsHeader: string | null;\n request: Request;\n searchParams: URLSearchParams;\n};\n\ntype RenderNotFoundOptions<TRoute> = {\n isRscRequest: boolean;\n matchedParams?: AppPageParams;\n middlewareContext: AppRscMiddlewareContext;\n request: Request;\n route: TRoute | null;\n scriptNonce?: string;\n};\n\ntype RenderPagesFallbackOptions = {\n isRscRequest: boolean;\n middlewareContext: AppRscMiddlewareContext;\n request: Request;\n url: URL;\n};\n\ntype NavigationContextValue = {\n params: AppPageParams;\n pathname: string;\n searchParams: URLSearchParams;\n};\n\ntype CreateAppRscHandlerOptions<TRoute extends AppRscHandlerRoute> = {\n basePath: string;\n clearRequestContext: () => void;\n configHeaders: NextHeader[];\n configRedirects: NextRedirect[];\n configRewrites: {\n afterFiles: NextRewrite[];\n beforeFiles: NextRewrite[];\n fallback: NextRewrite[];\n };\n dispatchMatchedPage: (options: DispatchMatchedPageOptions<TRoute>) => Promise<Response>;\n dispatchMatchedRouteHandler: (\n options: DispatchMatchedRouteHandlerOptions<TRoute>,\n ) => Promise<Response>;\n ensureInstrumentation?: () => Promise<void>;\n handleProgressiveActionRequest: (\n options: HandleProgressiveActionRequestOptions,\n ) => Promise<Response | null>;\n handleServerActionRequest: (\n options: HandleServerActionRequestOptions,\n ) => Promise<Response | null>;\n i18nConfig: NextI18nConfig | null;\n isMiddlewareProxy: boolean;\n loadPrerenderPagesRoutes?: () => Promise<unknown>;\n makeThenableParams: MakeThenableParams;\n matchRoute: (pathname: string) => AppRscRouteMatch<TRoute> | null;\n metadataRoutes: MetadataRoutes;\n middlewareModule: MiddlewareModule | null;\n publicFiles: ReadonlySet<string>;\n renderNotFound: (options: RenderNotFoundOptions<TRoute>) => Promise<Response | null>;\n renderPagesFallback?: (options: RenderPagesFallbackOptions) => Promise<Response | null>;\n rootParamNamesByPattern?: RootParamNamesMap;\n setNavigationContext: (context: NavigationContextValue) => void;\n staticParamsMap: StaticParamsMap;\n trailingSlash: boolean;\n validateDevRequestOrigin?: (request: Request) => Response | null;\n};\n\nfunction hasProperty<TKey extends PropertyKey>(\n value: object,\n key: TKey,\n): value is object & Record<TKey, unknown> {\n return key in value;\n}\n\nfunction isExecutionContextLike(value: unknown): value is ExecutionContextLike {\n if (!value || typeof value !== \"object\") return false;\n return hasProperty(value, \"waitUntil\") && typeof value.waitUntil === \"function\";\n}\n\nfunction redirectDestinationWithBasePath(destination: string, basePath: string): string {\n if (!basePath || isExternalUrl(destination) || hasBasePath(destination, basePath)) {\n return destination;\n }\n return basePath + destination;\n}\n\nasync function applyRewrite(\n options: {\n clearRequestContext: () => void;\n request: Request;\n requestContext: RequestContext;\n rewrites: NextRewrite[];\n },\n cleanPathname: string,\n): Promise<Response | string | null> {\n if (!options.rewrites.length) return null;\n\n const rewritten = matchRewrite(cleanPathname, options.rewrites, options.requestContext);\n if (!rewritten) return null;\n\n if (isExternalUrl(rewritten)) {\n options.clearRequestContext();\n return proxyExternalRequest(options.request, rewritten);\n }\n\n return rewritten;\n}\n\nasync function handleAppRscRequest<TRoute extends AppRscHandlerRoute>(\n options: CreateAppRscHandlerOptions<TRoute>,\n request: Request,\n preMiddlewareRequestContext: RequestContext,\n): Promise<Response> {\n const handlerStart = process.env.NODE_ENV !== \"production\" ? performance.now() : 0;\n\n if (process.env.NODE_ENV !== \"production\") {\n const originBlock = options.validateDevRequestOrigin?.(request);\n if (originBlock) return originBlock;\n }\n\n const normalized = normalizeRscRequest(request, options.basePath);\n if (normalized instanceof Response) return normalized;\n\n const { url, isRscRequest, interceptionContextHeader, mountedSlotsHeader } = normalized;\n let { pathname, cleanPathname } = normalized;\n\n const prerenderEndpointResponse = await handleAppPrerenderEndpoint(request, {\n isPrerenderEnabled() {\n return process.env.VINEXT_PRERENDER === \"1\";\n },\n loadPagesRoutes: options.loadPrerenderPagesRoutes,\n pathname,\n rootParamNamesByPattern: options.rootParamNamesByPattern,\n staticParamsMap: options.staticParamsMap,\n });\n if (prerenderEndpointResponse) return prerenderEndpointResponse;\n\n const trailingSlashRedirect = normalizeTrailingSlash(\n pathname,\n options.basePath,\n options.trailingSlash,\n url.search,\n );\n if (trailingSlashRedirect) return trailingSlashRedirect;\n\n const redirectPathname = pathname.endsWith(\".rsc\") ? pathname.slice(0, -4) : pathname;\n const redirect = matchRedirect(\n redirectPathname,\n options.configRedirects,\n preMiddlewareRequestContext,\n );\n if (redirect) {\n const destination = sanitizeDestination(\n redirectDestinationWithBasePath(redirect.destination, options.basePath),\n );\n return new Response(null, {\n status: redirect.permanent ? 308 : 307,\n headers: { Location: destination },\n });\n }\n\n const middlewareContext: AppRscMiddlewareContext = {\n headers: null,\n requestHeaders: null,\n status: null,\n };\n\n if (options.middlewareModule) {\n const middlewareResult = await applyAppMiddleware({\n basePath: options.basePath,\n cleanPathname,\n context: middlewareContext,\n i18nConfig: options.i18nConfig,\n isProxy: options.isMiddlewareProxy,\n module: options.middlewareModule,\n request,\n });\n if (middlewareResult.kind === \"response\") return middlewareResult.response;\n\n cleanPathname = middlewareResult.cleanPathname;\n if (middlewareResult.search !== null) {\n url.search = middlewareResult.search;\n }\n }\n\n const scriptNonce = getScriptNonceFromHeaderSources(request.headers, middlewareContext.headers);\n const postMiddlewareRequestContext = buildPostMwRequestContext(request);\n\n const beforeFilesRewrite = await applyRewrite(\n {\n clearRequestContext: options.clearRequestContext,\n request,\n requestContext: postMiddlewareRequestContext,\n rewrites: options.configRewrites.beforeFiles,\n },\n cleanPathname,\n );\n if (beforeFilesRewrite instanceof Response) return beforeFilesRewrite;\n if (beforeFilesRewrite) cleanPathname = beforeFilesRewrite;\n\n if (cleanPathname === \"/_vinext/image\") {\n const imageUrlResult = validateImageUrl(url.searchParams.get(\"url\"), request.url);\n if (imageUrlResult instanceof Response) return imageUrlResult;\n return Response.redirect(new URL(imageUrlResult, url.origin).href, 302);\n }\n\n const metadataRouteResponse = await handleMetadataRouteRequest({\n metadataRoutes: options.metadataRoutes,\n cleanPathname,\n makeThenableParams: options.makeThenableParams,\n });\n if (metadataRouteResponse) return metadataRouteResponse;\n\n const publicFileResponse = resolvePublicFileRoute({\n cleanPathname,\n middlewareContext,\n pathname,\n publicFiles: options.publicFiles,\n request,\n });\n if (publicFileResponse) {\n options.clearRequestContext();\n return publicFileResponse;\n }\n\n options.setNavigationContext({\n pathname: cleanPathname,\n searchParams: url.searchParams,\n params: {},\n });\n\n const actionId = request.headers.get(\"x-rsc-action\") ?? request.headers.get(\"next-action\");\n const contentType = request.headers.get(\"content-type\") || \"\";\n\n const progressiveActionResponse = await options.handleProgressiveActionRequest({\n actionId,\n cleanPathname,\n contentType,\n middlewareContext,\n request,\n });\n if (progressiveActionResponse) return progressiveActionResponse;\n\n const serverActionResponse = await options.handleServerActionRequest({\n actionId,\n cleanPathname,\n contentType,\n interceptionContext: interceptionContextHeader,\n isRscRequest,\n middlewareContext,\n mountedSlotsHeader,\n request,\n searchParams: url.searchParams,\n });\n if (serverActionResponse) return serverActionResponse;\n\n const afterFilesRewrite = await applyRewrite(\n {\n clearRequestContext: options.clearRequestContext,\n request,\n requestContext: postMiddlewareRequestContext,\n rewrites: options.configRewrites.afterFiles,\n },\n cleanPathname,\n );\n if (afterFilesRewrite instanceof Response) return afterFilesRewrite;\n if (afterFilesRewrite) cleanPathname = afterFilesRewrite;\n\n let match = options.matchRoute(cleanPathname);\n if (!match) {\n const fallbackRewrite = await applyRewrite(\n {\n clearRequestContext: options.clearRequestContext,\n request,\n requestContext: postMiddlewareRequestContext,\n rewrites: options.configRewrites.fallback,\n },\n cleanPathname,\n );\n if (fallbackRewrite instanceof Response) return fallbackRewrite;\n if (fallbackRewrite) {\n cleanPathname = fallbackRewrite;\n match = options.matchRoute(cleanPathname);\n }\n }\n\n if (!match) {\n const pagesFallbackResponse = await options.renderPagesFallback?.({\n isRscRequest,\n middlewareContext,\n request,\n url,\n });\n if (pagesFallbackResponse) {\n options.clearRequestContext();\n return pagesFallbackResponse;\n }\n\n const notFoundResponse = await options.renderNotFound({\n isRscRequest,\n middlewareContext,\n request,\n route: null,\n scriptNonce,\n });\n if (notFoundResponse) return notFoundResponse;\n\n options.clearRequestContext();\n const headers = new Headers();\n mergeMiddlewareResponseHeaders(headers, middlewareContext.headers);\n return new Response(\"Not Found\", { status: 404, headers });\n }\n\n const { route, params } = match;\n options.setNavigationContext({\n pathname: cleanPathname,\n searchParams: url.searchParams,\n params,\n });\n setRootParams(pickRootParams(params, route.rootParamNames));\n\n if (route.routeHandler) {\n setCurrentFetchSoftTags(\n buildPageCacheTags(cleanPathname, [], [...route.routeSegments], \"route\"),\n );\n return options.dispatchMatchedRouteHandler({\n cleanPathname,\n middlewareContext,\n params,\n request,\n route,\n searchParams: url.searchParams,\n });\n }\n\n return options.dispatchMatchedPage({\n cleanPathname,\n handlerStart,\n interceptionContext: interceptionContextHeader,\n isRscRequest,\n middlewareContext,\n mountedSlotsHeader,\n params,\n request,\n route,\n scriptNonce,\n searchParams: url.searchParams,\n });\n}\n\nexport function createAppRscHandler<TRoute extends AppRscHandlerRoute>(\n options: CreateAppRscHandlerOptions<TRoute>,\n): (request: Request, ctx: unknown) => Promise<Response> {\n return async function appRscHandler(request, ctx) {\n await options.ensureInstrumentation?.();\n\n const executionContext = isExecutionContextLike(ctx)\n ? ctx\n : (getRequestExecutionContext() ?? null);\n const headersContext = headersContextFromRequest(request);\n const requestContext = createRequestContext({\n headersContext,\n executionContext,\n unstableCacheRevalidation: \"background\",\n });\n\n return runWithRequestContext(requestContext, () =>\n runWithPrerenderWorkUnit(\n async () => {\n ensureFetchPatch();\n const preMiddlewareRequestContext = requestContextFromRequest(request);\n let response: Response;\n\n try {\n response = await handleAppRscRequest(options, request, preMiddlewareRequestContext);\n } catch (error) {\n if (process.env.NODE_ENV !== \"production\") {\n flattenErrorCauses(error);\n }\n throw error;\n }\n\n return finalizeAppRscResponse(response, request, {\n basePath: options.basePath,\n configHeaders: options.configHeaders,\n requestContext: preMiddlewareRequestContext,\n });\n },\n { route: () => new URL(request.url).pathname },\n ),\n );\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"app-rsc-handler.js","names":[],"sources":["../../src/server/app-rsc-handler.ts"],"sourcesContent":["import type {\n NextHeader,\n NextI18nConfig,\n NextRedirect,\n NextRewrite,\n} from \"../config/next-config.js\";\nimport {\n isExternalUrl,\n matchRedirect,\n matchRewrite,\n proxyExternalRequest,\n requestContextFromRequest,\n sanitizeDestination,\n} from \"../config/config-matchers.js\";\nimport { headersContextFromRequest } from \"vinext/shims/headers\";\nimport { ensureFetchPatch, setCurrentFetchSoftTags } from \"vinext/shims/fetch-cache\";\nimport {\n getRequestExecutionContext,\n type ExecutionContextLike,\n} from \"vinext/shims/request-context\";\nimport { pickRootParams, setRootParams } from \"vinext/shims/root-params\";\nimport { createRequestContext, runWithRequestContext } from \"vinext/shims/unified-request-context\";\nimport { flattenErrorCauses } from \"../utils/error-cause.js\";\nimport { hasBasePath } from \"../utils/base-path.js\";\nimport { applyAppMiddleware, type AppMiddlewareContext } from \"./app-middleware.js\";\nimport { mergeMiddlewareResponseHeaders } from \"./app-page-response.js\";\nimport { handleAppPrerenderEndpoint } from \"./app-prerender-endpoints.js\";\nimport {\n createRscRedirectLocation,\n resolveInvalidRscCacheBustingRequest,\n stripRscCacheBustingSearchParam,\n stripRscSuffix,\n} from \"./app-rsc-cache-busting.js\";\nimport { finalizeAppRscResponse } from \"./app-rsc-response-finalizer.js\";\nimport { normalizeRscRequest } from \"./app-rsc-request-normalization.js\";\nimport { notFoundResponse } from \"./http-error-responses.js\";\nimport { getScriptNonceFromHeaderSources } from \"./csp.js\";\nimport { buildPageCacheTags } from \"./implicit-tags.js\";\nimport { handleMetadataRouteRequest } from \"./metadata-route-response.js\";\nimport type { MiddlewareModule } from \"./middleware-runtime.js\";\nimport { runWithPrerenderWorkUnit } from \"./prerender-work-unit-setup.js\";\nimport { buildPostMwRequestContext } from \"./app-post-middleware-context.js\";\nimport {\n cloneRequestWithHeaders,\n filterInternalHeaders,\n normalizeTrailingSlash,\n resolvePublicFileRoute,\n validateImageUrl,\n} from \"./request-pipeline.js\";\n\ntype AppPageParams = Record<string, string | string[]>;\ntype RequestContext = ReturnType<typeof requestContextFromRequest>;\ntype MetadataRoutes = Parameters<typeof handleMetadataRouteRequest>[0][\"metadataRoutes\"];\ntype MakeThenableParams = Parameters<typeof handleMetadataRouteRequest>[0][\"makeThenableParams\"];\ntype StaticParamsMap = Parameters<typeof handleAppPrerenderEndpoint>[1][\"staticParamsMap\"];\ntype RootParamNamesMap = Parameters<\n typeof handleAppPrerenderEndpoint\n>[1][\"rootParamNamesByPattern\"];\n\ntype AppRscMiddlewareContext = AppMiddlewareContext;\n\ntype AppRscHandlerRoute = {\n page?: unknown;\n pattern: string;\n rootParamNames?: readonly string[];\n routeHandler?: unknown;\n routeSegments: readonly string[];\n};\n\ntype AppRscRouteMatch<TRoute> = {\n params: AppPageParams;\n route: TRoute;\n};\n\ntype DispatchMatchedPageOptions<TRoute> = {\n cleanPathname: string;\n handlerStart: number;\n interceptionContext: string | null;\n isRscRequest: boolean;\n middlewareContext: AppRscMiddlewareContext;\n mountedSlotsHeader: string | null;\n params: AppPageParams;\n request: Request;\n route: TRoute;\n scriptNonce?: string;\n searchParams: URLSearchParams;\n};\n\ntype DispatchMatchedRouteHandlerOptions<TRoute> = {\n cleanPathname: string;\n middlewareContext: AppRscMiddlewareContext;\n params: AppPageParams;\n request: Request;\n route: TRoute;\n searchParams: URLSearchParams;\n};\n\ntype HandleProgressiveActionRequestOptions = {\n actionId: string | null;\n cleanPathname: string;\n contentType: string;\n middlewareContext: AppRscMiddlewareContext;\n request: Request;\n};\n\ntype HandleServerActionRequestOptions = {\n actionId: string | null;\n cleanPathname: string;\n contentType: string;\n interceptionContext: string | null;\n isRscRequest: boolean;\n middlewareContext: AppRscMiddlewareContext;\n mountedSlotsHeader: string | null;\n request: Request;\n searchParams: URLSearchParams;\n};\n\ntype RenderNotFoundOptions<TRoute> = {\n isRscRequest: boolean;\n matchedParams?: AppPageParams;\n middlewareContext: AppRscMiddlewareContext;\n request: Request;\n route: TRoute | null;\n scriptNonce?: string;\n};\n\ntype RenderPagesFallbackOptions = {\n isRscRequest: boolean;\n middlewareContext: AppRscMiddlewareContext;\n request: Request;\n url: URL;\n};\n\ntype NavigationContextValue = {\n params: AppPageParams;\n pathname: string;\n searchParams: URLSearchParams;\n};\n\ntype CreateAppRscHandlerOptions<TRoute extends AppRscHandlerRoute> = {\n basePath: string;\n clearRequestContext: () => void;\n configHeaders: NextHeader[];\n configRedirects: NextRedirect[];\n configRewrites: {\n afterFiles: NextRewrite[];\n beforeFiles: NextRewrite[];\n fallback: NextRewrite[];\n };\n dispatchMatchedPage: (options: DispatchMatchedPageOptions<TRoute>) => Promise<Response>;\n dispatchMatchedRouteHandler: (\n options: DispatchMatchedRouteHandlerOptions<TRoute>,\n ) => Promise<Response>;\n ensureInstrumentation?: () => Promise<void>;\n handleProgressiveActionRequest: (\n options: HandleProgressiveActionRequestOptions,\n ) => Promise<Response | null>;\n handleServerActionRequest: (\n options: HandleServerActionRequestOptions,\n ) => Promise<Response | null>;\n i18nConfig: NextI18nConfig | null;\n isMiddlewareProxy: boolean;\n loadPrerenderPagesRoutes?: () => Promise<unknown>;\n makeThenableParams: MakeThenableParams;\n matchRoute: (pathname: string) => AppRscRouteMatch<TRoute> | null;\n metadataRoutes: MetadataRoutes;\n middlewareModule: MiddlewareModule | null;\n publicFiles: ReadonlySet<string>;\n renderNotFound: (options: RenderNotFoundOptions<TRoute>) => Promise<Response | null>;\n renderPagesFallback?: (options: RenderPagesFallbackOptions) => Promise<Response | null>;\n rootParamNamesByPattern?: RootParamNamesMap;\n setNavigationContext: (context: NavigationContextValue) => void;\n staticParamsMap: StaticParamsMap;\n trailingSlash: boolean;\n validateDevRequestOrigin?: (request: Request) => Response | null;\n};\n\nfunction hasProperty<TKey extends PropertyKey>(\n value: object,\n key: TKey,\n): value is object & Record<TKey, unknown> {\n return key in value;\n}\n\nfunction isExecutionContextLike(value: unknown): value is ExecutionContextLike {\n if (!value || typeof value !== \"object\") return false;\n return hasProperty(value, \"waitUntil\") && typeof value.waitUntil === \"function\";\n}\n\nfunction redirectDestinationWithBasePath(destination: string, basePath: string): string {\n if (!basePath || isExternalUrl(destination) || hasBasePath(destination, basePath)) {\n return destination;\n }\n return basePath + destination;\n}\n\nasync function applyRewrite(\n options: {\n clearRequestContext: () => void;\n request: Request;\n requestContext: RequestContext;\n rewrites: NextRewrite[];\n },\n cleanPathname: string,\n): Promise<Response | string | null> {\n if (!options.rewrites.length) return null;\n\n const rewritten = matchRewrite(cleanPathname, options.rewrites, options.requestContext);\n if (!rewritten) return null;\n\n if (isExternalUrl(rewritten)) {\n options.clearRequestContext();\n return proxyExternalRequest(options.request, rewritten);\n }\n\n return rewritten;\n}\n\nasync function handleAppRscRequest<TRoute extends AppRscHandlerRoute>(\n options: CreateAppRscHandlerOptions<TRoute>,\n request: Request,\n preMiddlewareRequestContext: RequestContext,\n): Promise<Response> {\n const handlerStart = process.env.NODE_ENV !== \"production\" ? performance.now() : 0;\n\n if (process.env.NODE_ENV !== \"production\") {\n const originBlock = options.validateDevRequestOrigin?.(request);\n if (originBlock) return originBlock;\n }\n\n const normalized = normalizeRscRequest(request, options.basePath);\n if (normalized instanceof Response) return normalized;\n\n const { url, isRscRequest, interceptionContextHeader, mountedSlotsHeader } = normalized;\n let { pathname, cleanPathname } = normalized;\n\n const prerenderEndpointResponse = await handleAppPrerenderEndpoint(request, {\n isPrerenderEnabled() {\n return process.env.VINEXT_PRERENDER === \"1\";\n },\n loadPagesRoutes: options.loadPrerenderPagesRoutes,\n pathname,\n rootParamNamesByPattern: options.rootParamNamesByPattern,\n staticParamsMap: options.staticParamsMap,\n });\n if (prerenderEndpointResponse) return prerenderEndpointResponse;\n\n const trailingSlashRedirect = normalizeTrailingSlash(\n pathname,\n options.basePath,\n options.trailingSlash,\n url.search,\n );\n if (trailingSlashRedirect) return trailingSlashRedirect;\n\n const redirectPathname = stripRscSuffix(pathname);\n const redirect = matchRedirect(\n redirectPathname,\n options.configRedirects,\n preMiddlewareRequestContext,\n );\n if (redirect) {\n const destination = sanitizeDestination(\n redirectDestinationWithBasePath(redirect.destination, options.basePath),\n );\n const location =\n isRscRequest && request.headers.get(\"RSC\") === \"1\"\n ? await createRscRedirectLocation(destination, request)\n : destination;\n return new Response(null, {\n status: redirect.permanent ? 308 : 307,\n headers: { Location: location },\n });\n }\n\n const rscCacheBustingRedirect = await resolveInvalidRscCacheBustingRequest({\n isRscRequest,\n request,\n });\n if (rscCacheBustingRedirect) return rscCacheBustingRedirect;\n\n const middlewareContext: AppRscMiddlewareContext = {\n headers: null,\n requestHeaders: null,\n status: null,\n };\n\n if (options.middlewareModule) {\n const middlewareResult = await applyAppMiddleware({\n basePath: options.basePath,\n cleanPathname,\n context: middlewareContext,\n i18nConfig: options.i18nConfig,\n isProxy: options.isMiddlewareProxy,\n module: options.middlewareModule,\n request,\n });\n if (middlewareResult.kind === \"response\") return middlewareResult.response;\n\n cleanPathname = middlewareResult.cleanPathname;\n if (middlewareResult.search !== null) {\n url.search = middlewareResult.search;\n }\n }\n\n const scriptNonce = getScriptNonceFromHeaderSources(request.headers, middlewareContext.headers);\n const postMiddlewareRequestContext = buildPostMwRequestContext(request);\n\n const beforeFilesRewrite = await applyRewrite(\n {\n clearRequestContext: options.clearRequestContext,\n request,\n requestContext: postMiddlewareRequestContext,\n rewrites: options.configRewrites.beforeFiles,\n },\n cleanPathname,\n );\n if (beforeFilesRewrite instanceof Response) return beforeFilesRewrite;\n if (beforeFilesRewrite) cleanPathname = beforeFilesRewrite;\n\n if (cleanPathname === \"/_vinext/image\") {\n const imageUrlResult = validateImageUrl(url.searchParams.get(\"url\"), request.url);\n if (imageUrlResult instanceof Response) return imageUrlResult;\n return Response.redirect(new URL(imageUrlResult, url.origin).href, 302);\n }\n\n const metadataRouteResponse = await handleMetadataRouteRequest({\n metadataRoutes: options.metadataRoutes,\n cleanPathname,\n makeThenableParams: options.makeThenableParams,\n });\n if (metadataRouteResponse) return metadataRouteResponse;\n\n const publicFileResponse = resolvePublicFileRoute({\n cleanPathname,\n middlewareContext,\n pathname,\n publicFiles: options.publicFiles,\n request,\n });\n if (publicFileResponse) {\n options.clearRequestContext();\n return publicFileResponse;\n }\n\n if (isRscRequest) {\n stripRscCacheBustingSearchParam(url);\n }\n\n options.setNavigationContext({\n pathname: cleanPathname,\n searchParams: url.searchParams,\n params: {},\n });\n\n const actionId = request.headers.get(\"x-rsc-action\") ?? request.headers.get(\"next-action\");\n const contentType = request.headers.get(\"content-type\") || \"\";\n\n const progressiveActionResponse = await options.handleProgressiveActionRequest({\n actionId,\n cleanPathname,\n contentType,\n middlewareContext,\n request,\n });\n if (progressiveActionResponse) return progressiveActionResponse;\n\n const serverActionResponse = await options.handleServerActionRequest({\n actionId,\n cleanPathname,\n contentType,\n interceptionContext: interceptionContextHeader,\n isRscRequest,\n middlewareContext,\n mountedSlotsHeader,\n request,\n searchParams: url.searchParams,\n });\n if (serverActionResponse) return serverActionResponse;\n\n const afterFilesRewrite = await applyRewrite(\n {\n clearRequestContext: options.clearRequestContext,\n request,\n requestContext: postMiddlewareRequestContext,\n rewrites: options.configRewrites.afterFiles,\n },\n cleanPathname,\n );\n if (afterFilesRewrite instanceof Response) return afterFilesRewrite;\n if (afterFilesRewrite) cleanPathname = afterFilesRewrite;\n\n let match = options.matchRoute(cleanPathname);\n if (!match) {\n const fallbackRewrite = await applyRewrite(\n {\n clearRequestContext: options.clearRequestContext,\n request,\n requestContext: postMiddlewareRequestContext,\n rewrites: options.configRewrites.fallback,\n },\n cleanPathname,\n );\n if (fallbackRewrite instanceof Response) return fallbackRewrite;\n if (fallbackRewrite) {\n cleanPathname = fallbackRewrite;\n match = options.matchRoute(cleanPathname);\n }\n }\n\n if (!match) {\n const pagesFallbackResponse = await options.renderPagesFallback?.({\n isRscRequest,\n middlewareContext,\n request,\n url,\n });\n if (pagesFallbackResponse) {\n options.clearRequestContext();\n return pagesFallbackResponse;\n }\n\n const renderedNotFoundResponse = await options.renderNotFound({\n isRscRequest,\n middlewareContext,\n request,\n route: null,\n scriptNonce,\n });\n if (renderedNotFoundResponse) return renderedNotFoundResponse;\n\n options.clearRequestContext();\n const headers = new Headers();\n mergeMiddlewareResponseHeaders(headers, middlewareContext.headers);\n return notFoundResponse({ headers });\n }\n\n const { route, params } = match;\n options.setNavigationContext({\n pathname: cleanPathname,\n searchParams: url.searchParams,\n params,\n });\n setRootParams(pickRootParams(params, route.rootParamNames));\n\n if (route.routeHandler) {\n setCurrentFetchSoftTags(\n buildPageCacheTags(cleanPathname, [], [...route.routeSegments], \"route\"),\n );\n return options.dispatchMatchedRouteHandler({\n cleanPathname,\n middlewareContext,\n params,\n request,\n route,\n searchParams: url.searchParams,\n });\n }\n\n return options.dispatchMatchedPage({\n cleanPathname,\n handlerStart,\n interceptionContext: interceptionContextHeader,\n isRscRequest,\n middlewareContext,\n mountedSlotsHeader,\n params,\n request,\n route,\n scriptNonce,\n searchParams: url.searchParams,\n });\n}\n\nexport function createAppRscHandler<TRoute extends AppRscHandlerRoute>(\n options: CreateAppRscHandlerOptions<TRoute>,\n): (request: Request, ctx: unknown) => Promise<Response> {\n return async function appRscHandler(rawRequest, ctx) {\n await options.ensureInstrumentation?.();\n\n // Strip forged internal headers at the App Router request boundary.\n // Must happen BEFORE headersContextFromRequest() and\n // requestContextFromRequest() so the captured context never contains\n // attacker-controlled internal headers. This is the correct boundary\n // for pure App Router requests; in hybrid app+pages mode the connect\n // handler already filtered headers upstream and x-vinext-mw-ctx\n // (not in INTERNAL_HEADERS) carries the forwarded middleware context.\n // srvx's NodeRequestHeaders reads from rawHeaders for iteration but falls\n // back to req.headers for .get() / .has(). In the dev server we add\n // x-vinext-mw-ctx to req.headers after the Request is built, so it is\n // visible to .get() but lost when filterInternalHeaders iterates. Read it\n // BEFORE iterating so applyForwardedMiddlewareContext can skip middleware.\n const mwCtx = rawRequest.headers.get(\"x-vinext-mw-ctx\");\n const filteredHeaders = filterInternalHeaders(rawRequest.headers);\n if (mwCtx !== null) {\n filteredHeaders.set(\"x-vinext-mw-ctx\", mwCtx);\n }\n const request = cloneRequestWithHeaders(rawRequest, filteredHeaders);\n\n const executionContext = isExecutionContextLike(ctx)\n ? ctx\n : (getRequestExecutionContext() ?? null);\n const headersContext = headersContextFromRequest(request);\n const requestContext = createRequestContext({\n headersContext,\n executionContext,\n unstableCacheRevalidation: \"background\",\n });\n\n return runWithRequestContext(requestContext, () =>\n runWithPrerenderWorkUnit(\n async () => {\n ensureFetchPatch();\n const preMiddlewareRequestContext = requestContextFromRequest(request);\n let response: Response;\n\n try {\n response = await handleAppRscRequest(options, request, preMiddlewareRequestContext);\n } catch (error) {\n if (process.env.NODE_ENV !== \"production\") {\n flattenErrorCauses(error);\n }\n throw error;\n }\n\n return finalizeAppRscResponse(response, request, {\n basePath: options.basePath,\n configHeaders: options.configHeaders,\n requestContext: preMiddlewareRequestContext,\n });\n },\n { route: () => new URL(request.url).pathname },\n ),\n );\n };\n}\n"],"mappings":"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"}
|
|
@@ -4,7 +4,7 @@ import { normalizeMountedSlotsHeader } from "./app-mounted-slots-header.js";
|
|
|
4
4
|
type NormalizedRscRequest = {
|
|
5
5
|
/** Parsed URL. Callers may mutate `url.search` after middleware runs. */url: URL; /** Normalized pathname with basePath stripped. Used for all internal routing. */
|
|
6
6
|
pathname: string; /** Pathname with `.rsc` suffix removed. Used for route matching and navigation context. */
|
|
7
|
-
cleanPathname: string; /** True when the
|
|
7
|
+
cleanPathname: string; /** True when the request targets a canonical `.rsc` payload URL. */
|
|
8
8
|
isRscRequest: boolean; /** Sanitized X-Vinext-Interception-Context header (null bytes stripped). null when absent. */
|
|
9
9
|
interceptionContextHeader: string | null; /** Normalized x-vinext-mounted-slots header (deduplicated, sorted). null when absent or blank. */
|
|
10
10
|
mountedSlotsHeader: string | null;
|
|
@@ -26,7 +26,9 @@ type NormalizedRscRequest = {
|
|
|
26
26
|
* 4. Collapse double-slashes, resolve `.` and `..` segments (normalizePath)
|
|
27
27
|
* 5. basePath check + strip — 404 when pathname lacks the basePath prefix.
|
|
28
28
|
* `/__vinext/` bypasses this for internal prerender endpoints.
|
|
29
|
-
* 6. RSC detection: `.rsc` suffix
|
|
29
|
+
* 6. RSC detection: `.rsc` suffix only. RSC headers do not select payload
|
|
30
|
+
* rendering at the canonical HTML URL, so caches that ignore Vary cannot
|
|
31
|
+
* store Flight responses under HTML URLs.
|
|
30
32
|
* 7. cleanPathname — pathname with `.rsc` suffix stripped
|
|
31
33
|
* 8. Sanitize X-Vinext-Interception-Context — strip null bytes (header injection)
|
|
32
34
|
* 9. Normalize x-vinext-mounted-slots — dedup and sort for canonical cache keys
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { normalizePathnameForRouteMatchStrict } from "../routing/utils.js";
|
|
2
|
-
import { normalizePath } from "./normalize-path.js";
|
|
3
2
|
import { hasBasePath, stripBasePath } from "../utils/base-path.js";
|
|
3
|
+
import { normalizePath } from "./normalize-path.js";
|
|
4
|
+
import { badRequestResponse, notFoundResponse } from "./http-error-responses.js";
|
|
4
5
|
import { guardProtocolRelativeUrl } from "./request-pipeline.js";
|
|
5
6
|
import { normalizeMountedSlotsHeader } from "./app-mounted-slots-header.js";
|
|
7
|
+
import { stripRscSuffix } from "./app-rsc-cache-busting.js";
|
|
6
8
|
//#region src/server/app-rsc-request-normalization.ts
|
|
7
9
|
/**
|
|
8
10
|
* Normalize an App Router RSC request.
|
|
@@ -21,7 +23,9 @@ import { normalizeMountedSlotsHeader } from "./app-mounted-slots-header.js";
|
|
|
21
23
|
* 4. Collapse double-slashes, resolve `.` and `..` segments (normalizePath)
|
|
22
24
|
* 5. basePath check + strip — 404 when pathname lacks the basePath prefix.
|
|
23
25
|
* `/__vinext/` bypasses this for internal prerender endpoints.
|
|
24
|
-
* 6. RSC detection: `.rsc` suffix
|
|
26
|
+
* 6. RSC detection: `.rsc` suffix only. RSC headers do not select payload
|
|
27
|
+
* rendering at the canonical HTML URL, so caches that ignore Vary cannot
|
|
28
|
+
* store Flight responses under HTML URLs.
|
|
25
29
|
* 7. cleanPathname — pathname with `.rsc` suffix stripped
|
|
26
30
|
* 8. Sanitize X-Vinext-Interception-Context — strip null bytes (header injection)
|
|
27
31
|
* 9. Normalize x-vinext-mounted-slots — dedup and sort for canonical cache keys
|
|
@@ -37,15 +41,15 @@ function normalizeRscRequest(request, basePath) {
|
|
|
37
41
|
try {
|
|
38
42
|
decoded = normalizePathnameForRouteMatchStrict(url.pathname);
|
|
39
43
|
} catch {
|
|
40
|
-
return
|
|
44
|
+
return badRequestResponse();
|
|
41
45
|
}
|
|
42
46
|
let pathname = normalizePath(decoded);
|
|
43
47
|
if (basePath) {
|
|
44
|
-
if (!hasBasePath(pathname, basePath) && !pathname.startsWith("/__vinext/")) return
|
|
48
|
+
if (!hasBasePath(pathname, basePath) && !pathname.startsWith("/__vinext/")) return notFoundResponse();
|
|
45
49
|
pathname = stripBasePath(pathname, basePath);
|
|
46
50
|
}
|
|
47
|
-
const isRscRequest = pathname.endsWith(".rsc")
|
|
48
|
-
const cleanPathname = pathname
|
|
51
|
+
const isRscRequest = pathname.endsWith(".rsc");
|
|
52
|
+
const cleanPathname = stripRscSuffix(pathname);
|
|
49
53
|
const interceptionContextHeader = request.headers.get("X-Vinext-Interception-Context")?.replaceAll("\0", "") || null;
|
|
50
54
|
const mountedSlotsHeader = normalizeMountedSlotsHeader(request.headers.get("x-vinext-mounted-slots"));
|
|
51
55
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-rsc-request-normalization.js","names":[],"sources":["../../src/server/app-rsc-request-normalization.ts"],"sourcesContent":["import { normalizePath } from \"./normalize-path.js\";\nimport { normalizePathnameForRouteMatchStrict } from \"../routing/utils.js\";\nimport { guardProtocolRelativeUrl } from \"./request-pipeline.js\";\nimport { hasBasePath, stripBasePath } from \"../utils/base-path.js\";\nimport { normalizeMountedSlotsHeader } from \"./app-mounted-slots-header.js\";\n\nexport { normalizeMountedSlotsHeader } from \"./app-mounted-slots-header.js\";\n\nexport type NormalizedRscRequest = {\n /** Parsed URL. Callers may mutate `url.search` after middleware runs. */\n url: URL;\n /** Normalized pathname with basePath stripped. Used for all internal routing. */\n pathname: string;\n /** Pathname with `.rsc` suffix removed. Used for route matching and navigation context. */\n cleanPathname: string;\n /** True when the
|
|
1
|
+
{"version":3,"file":"app-rsc-request-normalization.js","names":[],"sources":["../../src/server/app-rsc-request-normalization.ts"],"sourcesContent":["import { normalizePath } from \"./normalize-path.js\";\nimport { normalizePathnameForRouteMatchStrict } from \"../routing/utils.js\";\nimport { guardProtocolRelativeUrl } from \"./request-pipeline.js\";\nimport { hasBasePath, stripBasePath } from \"../utils/base-path.js\";\nimport { normalizeMountedSlotsHeader } from \"./app-mounted-slots-header.js\";\nimport { stripRscSuffix } from \"./app-rsc-cache-busting.js\";\nimport { badRequestResponse, notFoundResponse } from \"./http-error-responses.js\";\n\nexport { normalizeMountedSlotsHeader } from \"./app-mounted-slots-header.js\";\n\nexport type NormalizedRscRequest = {\n /** Parsed URL. Callers may mutate `url.search` after middleware runs. */\n url: URL;\n /** Normalized pathname with basePath stripped. Used for all internal routing. */\n pathname: string;\n /** Pathname with `.rsc` suffix removed. Used for route matching and navigation context. */\n cleanPathname: string;\n /** True when the request targets a canonical `.rsc` payload URL. */\n isRscRequest: boolean;\n /** Sanitized X-Vinext-Interception-Context header (null bytes stripped). null when absent. */\n interceptionContextHeader: string | null;\n /** Normalized x-vinext-mounted-slots header (deduplicated, sorted). null when absent or blank. */\n mountedSlotsHeader: string | null;\n};\n\n/**\n * Normalize an App Router RSC request.\n *\n * Performs all security-sensitive and compatibility-sensitive preprocessing before\n * route matching. The ordering of steps is security-critical — changing it introduces\n * vulnerabilities:\n *\n * 1. Parse URL\n * 2. Protocol-relative URL guard — on the raw pathname, BEFORE normalizePath collapses\n * `//` to `/`. If the guard ran after normalization, `//evil.com` → `/evil.com`\n * would bypass the check and reach the trailing-slash redirector, which echoes the\n * path into a `Location` header that browsers interpret as protocol-relative.\n * 3. Strict percent-decode each segment — throws on malformed sequences (→ 400). Must\n * run before basePath check so %2F-encoded slashes cannot create fake basePath prefixes.\n * 4. Collapse double-slashes, resolve `.` and `..` segments (normalizePath)\n * 5. basePath check + strip — 404 when pathname lacks the basePath prefix.\n * `/__vinext/` bypasses this for internal prerender endpoints.\n * 6. RSC detection: `.rsc` suffix only. RSC headers do not select payload\n * rendering at the canonical HTML URL, so caches that ignore Vary cannot\n * store Flight responses under HTML URLs.\n * 7. cleanPathname — pathname with `.rsc` suffix stripped\n * 8. Sanitize X-Vinext-Interception-Context — strip null bytes (header injection)\n * 9. Normalize x-vinext-mounted-slots — dedup and sort for canonical cache keys\n *\n * @returns A 400 or 404 Response for invalid or out-of-scope inputs,\n * or a NormalizedRscRequest for valid requests.\n */\nexport function normalizeRscRequest(\n request: Request,\n basePath: string,\n): Response | NormalizedRscRequest {\n const url = new URL(request.url);\n\n // Step 2: Guard against protocol-relative open redirects on the raw pathname.\n // normalizePath (step 4) would collapse //evil.com to /evil.com, causing the\n // guard to miss it. Raw pathname must be checked first.\n const protoGuard = guardProtocolRelativeUrl(url.pathname);\n if (protoGuard) return protoGuard;\n\n // Step 3: Strict segment-wise percent-decode. Preserves encoded path delimiters\n // (%2F stays %2F) to prevent encoded slashes from acting as path separators.\n // Throws on malformed sequences like %GG — caller must return 400.\n let decoded: string;\n try {\n decoded = normalizePathnameForRouteMatchStrict(url.pathname);\n } catch {\n return badRequestResponse();\n }\n\n // Step 4: Collapse double-slashes and resolve . / .. segments.\n let pathname = normalizePath(decoded);\n\n // Step 5: basePath check and strip.\n // Skipped when basePath is empty (no basePath configured).\n // /__vinext/ prefix bypasses the check for internal prerender endpoints\n // that must be reachable regardless of basePath configuration.\n if (basePath) {\n if (!hasBasePath(pathname, basePath) && !pathname.startsWith(\"/__vinext/\")) {\n return notFoundResponse();\n }\n pathname = stripBasePath(pathname, basePath);\n }\n\n // Steps 6-7: RSC detection and cleanPathname.\n const isRscRequest = pathname.endsWith(\".rsc\");\n const cleanPathname = stripRscSuffix(pathname);\n\n // Step 8: Sanitize X-Vinext-Interception-Context.\n // Null bytes in header values can be used for injection in some HTTP stacks.\n const interceptionContextHeader =\n request.headers.get(\"X-Vinext-Interception-Context\")?.replaceAll(\"\\0\", \"\") || null;\n\n // Step 9: Normalize mounted-slots header for canonical cache keying.\n const mountedSlotsHeader = normalizeMountedSlotsHeader(\n request.headers.get(\"x-vinext-mounted-slots\"),\n );\n\n return {\n url,\n pathname,\n cleanPathname,\n isRscRequest,\n interceptionContextHeader,\n mountedSlotsHeader,\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoDA,SAAgB,oBACd,SACA,UACiC;CACjC,MAAM,MAAM,IAAI,IAAI,QAAQ,IAAI;CAKhC,MAAM,aAAa,yBAAyB,IAAI,SAAS;AACzD,KAAI,WAAY,QAAO;CAKvB,IAAI;AACJ,KAAI;AACF,YAAU,qCAAqC,IAAI,SAAS;SACtD;AACN,SAAO,oBAAoB;;CAI7B,IAAI,WAAW,cAAc,QAAQ;AAMrC,KAAI,UAAU;AACZ,MAAI,CAAC,YAAY,UAAU,SAAS,IAAI,CAAC,SAAS,WAAW,aAAa,CACxE,QAAO,kBAAkB;AAE3B,aAAW,cAAc,UAAU,SAAS;;CAI9C,MAAM,eAAe,SAAS,SAAS,OAAO;CAC9C,MAAM,gBAAgB,eAAe,SAAS;CAI9C,MAAM,4BACJ,QAAQ,QAAQ,IAAI,gCAAgC,EAAE,WAAW,MAAM,GAAG,IAAI;CAGhF,MAAM,qBAAqB,4BACzB,QAAQ,QAAQ,IAAI,yBAAyB,CAC9C;AAED,QAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACD"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { normalizePathnameForRouteMatch } from "../routing/utils.js";
|
|
2
|
-
import { normalizePath } from "./normalize-path.js";
|
|
3
2
|
import { stripBasePath } from "../utils/base-path.js";
|
|
3
|
+
import { normalizePath } from "./normalize-path.js";
|
|
4
4
|
import { applyConfigHeadersToResponse } from "./request-pipeline.js";
|
|
5
5
|
//#region src/server/app-rsc-response-finalizer.ts
|
|
6
6
|
/**
|
|
@@ -1,26 +1,30 @@
|
|
|
1
|
+
import { normalizePathnameForRouteMatch } from "../routing/utils.js";
|
|
1
2
|
import { buildRouteTrie, trieMatch } from "../routing/route-trie.js";
|
|
2
3
|
import { matchRoutePattern } from "../routing/route-pattern.js";
|
|
3
4
|
//#region src/server/app-rsc-route-matching.ts
|
|
4
5
|
function createRouteParams() {
|
|
5
6
|
return Object.create(null);
|
|
6
7
|
}
|
|
8
|
+
function appRscPathnameParts(pathname) {
|
|
9
|
+
const pathOnly = pathname.split("?")[0];
|
|
10
|
+
return normalizePathnameForRouteMatch(pathOnly === "/" ? "/" : pathOnly.replace(/\/$/, "")).split("/").filter(Boolean);
|
|
11
|
+
}
|
|
7
12
|
function createAppRscRouteMatcher(routes) {
|
|
8
13
|
const routeTrie = buildRouteTrie(routes);
|
|
9
14
|
const interceptLookup = createInterceptLookup(routes);
|
|
10
15
|
return {
|
|
11
16
|
matchRoute(url) {
|
|
12
|
-
|
|
13
|
-
return trieMatch(routeTrie, (pathname === "/" ? "/" : pathname.replace(/\/$/, "")).split("/").filter(Boolean));
|
|
17
|
+
return trieMatch(routeTrie, appRscPathnameParts(url));
|
|
14
18
|
},
|
|
15
19
|
findIntercept(pathname, sourcePathname = null) {
|
|
16
|
-
const urlParts = pathname
|
|
20
|
+
const urlParts = appRscPathnameParts(pathname);
|
|
17
21
|
for (const entry of interceptLookup) {
|
|
18
22
|
const params = matchAppRscRoutePattern(urlParts, entry.targetPatternParts);
|
|
19
23
|
if (params !== null) {
|
|
20
24
|
let sourceParams = createRouteParams();
|
|
21
25
|
if (sourcePathname !== null) {
|
|
22
26
|
const sourceRoute = routes[entry.sourceRouteIndex];
|
|
23
|
-
const sourceParts = sourcePathname
|
|
27
|
+
const sourceParts = appRscPathnameParts(sourcePathname);
|
|
24
28
|
const matchedSourceParams = sourceRoute ? matchAppRscRoutePattern(sourceParts, sourceRoute.patternParts) : null;
|
|
25
29
|
if (matchedSourceParams !== null) sourceParams = matchedSourceParams;
|
|
26
30
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-rsc-route-matching.js","names":[],"sources":["../../src/server/app-rsc-route-matching.ts"],"sourcesContent":["import { buildRouteTrie, trieMatch } from \"../routing/route-trie.js\";\nimport { matchRoutePattern, type RoutePatternParams } from \"../routing/route-pattern.js\";\n\ntype AppRscRouteParams = RoutePatternParams;\n\ntype AppRscInterceptForMatching = {\n targetPattern: string;\n interceptLayouts: readonly unknown[];\n page: unknown;\n params: readonly string[];\n};\n\ntype AppRscSlotForMatching = {\n intercepts?: readonly AppRscInterceptForMatching[];\n};\n\ntype AppRscRouteForMatching = {\n patternParts: string[];\n slots?: Record<string, AppRscSlotForMatching>;\n};\n\ntype AppRscInterceptMatch = AppRscInterceptLookupEntry & {\n matchedParams: AppRscRouteParams;\n};\n\ntype AppRscInterceptLookupEntry = {\n sourceRouteIndex: number;\n slotKey: string;\n targetPattern: string;\n targetPatternParts: string[];\n interceptLayouts: readonly unknown[];\n page: unknown;\n params: readonly string[];\n};\n\nfunction createRouteParams(): AppRscRouteParams {\n return Object.create(null);\n}\n\nexport function createAppRscRouteMatcher<Route extends AppRscRouteForMatching>(\n routes: Route[],\n): {\n matchRoute(url: string): { route: Route; params: AppRscRouteParams } | null;\n findIntercept(pathname: string, sourcePathname?: string | null): AppRscInterceptMatch | null;\n} {\n const routeTrie = buildRouteTrie(routes);\n const interceptLookup = createInterceptLookup(routes);\n\n return {\n matchRoute(url) {\n
|
|
1
|
+
{"version":3,"file":"app-rsc-route-matching.js","names":[],"sources":["../../src/server/app-rsc-route-matching.ts"],"sourcesContent":["import { buildRouteTrie, trieMatch } from \"../routing/route-trie.js\";\nimport { matchRoutePattern, type RoutePatternParams } from \"../routing/route-pattern.js\";\nimport { normalizePathnameForRouteMatch } from \"../routing/utils.js\";\n\ntype AppRscRouteParams = RoutePatternParams;\n\ntype AppRscInterceptForMatching = {\n targetPattern: string;\n interceptLayouts: readonly unknown[];\n page: unknown;\n params: readonly string[];\n};\n\ntype AppRscSlotForMatching = {\n intercepts?: readonly AppRscInterceptForMatching[];\n};\n\ntype AppRscRouteForMatching = {\n patternParts: string[];\n slots?: Record<string, AppRscSlotForMatching>;\n};\n\ntype AppRscInterceptMatch = AppRscInterceptLookupEntry & {\n matchedParams: AppRscRouteParams;\n};\n\ntype AppRscInterceptLookupEntry = {\n sourceRouteIndex: number;\n slotKey: string;\n targetPattern: string;\n targetPatternParts: string[];\n interceptLayouts: readonly unknown[];\n page: unknown;\n params: readonly string[];\n};\n\nfunction createRouteParams(): AppRscRouteParams {\n return Object.create(null);\n}\n\nfunction appRscPathnameParts(pathname: string): string[] {\n const pathOnly = pathname.split(\"?\")[0];\n const normalized = pathOnly === \"/\" ? \"/\" : pathOnly.replace(/\\/$/, \"\");\n return normalizePathnameForRouteMatch(normalized).split(\"/\").filter(Boolean);\n}\n\nexport function createAppRscRouteMatcher<Route extends AppRscRouteForMatching>(\n routes: Route[],\n): {\n matchRoute(url: string): { route: Route; params: AppRscRouteParams } | null;\n findIntercept(pathname: string, sourcePathname?: string | null): AppRscInterceptMatch | null;\n} {\n const routeTrie = buildRouteTrie(routes);\n const interceptLookup = createInterceptLookup(routes);\n\n return {\n matchRoute(url) {\n return trieMatch(routeTrie, appRscPathnameParts(url));\n },\n findIntercept(pathname, sourcePathname = null) {\n const urlParts = appRscPathnameParts(pathname);\n for (const entry of interceptLookup) {\n const params = matchAppRscRoutePattern(urlParts, entry.targetPatternParts);\n if (params !== null) {\n let sourceParams = createRouteParams();\n if (sourcePathname !== null) {\n const sourceRoute = routes[entry.sourceRouteIndex];\n const sourceParts = appRscPathnameParts(sourcePathname);\n const matchedSourceParams = sourceRoute\n ? matchAppRscRoutePattern(sourceParts, sourceRoute.patternParts)\n : null;\n if (matchedSourceParams !== null) {\n sourceParams = matchedSourceParams;\n }\n }\n return { ...entry, matchedParams: mergeMatchedParams(sourceParams, params) };\n }\n }\n return null;\n },\n };\n}\n\nfunction createInterceptLookup<Route extends AppRscRouteForMatching>(\n routes: Route[],\n): AppRscInterceptLookupEntry[] {\n const interceptLookup: AppRscInterceptLookupEntry[] = [];\n for (let routeIndex = 0; routeIndex < routes.length; routeIndex++) {\n const route = routes[routeIndex];\n if (!route.slots) continue;\n for (const [slotKey, slotModule] of Object.entries(route.slots)) {\n if (!slotModule.intercepts) continue;\n for (const intercept of slotModule.intercepts) {\n interceptLookup.push({\n sourceRouteIndex: routeIndex,\n slotKey,\n targetPattern: intercept.targetPattern,\n targetPatternParts: intercept.targetPattern.split(\"/\").filter(Boolean),\n interceptLayouts: intercept.interceptLayouts,\n page: intercept.page,\n params: intercept.params,\n });\n }\n }\n }\n return interceptLookup;\n}\n\nexport function matchAppRscRoutePattern(\n urlParts: string[],\n patternParts: string[],\n): AppRscRouteParams | null {\n return matchRoutePattern(urlParts, patternParts);\n}\n\nfunction mergeMatchedParams(\n sourceParams: AppRscRouteParams,\n targetParams: AppRscRouteParams,\n): AppRscRouteParams {\n return Object.assign(createRouteParams(), sourceParams, targetParams);\n}\n"],"mappings":";;;;AAoCA,SAAS,oBAAuC;AAC9C,QAAO,OAAO,OAAO,KAAK;;AAG5B,SAAS,oBAAoB,UAA4B;CACvD,MAAM,WAAW,SAAS,MAAM,IAAI,CAAC;AAErC,QAAO,+BADY,aAAa,MAAM,MAAM,SAAS,QAAQ,OAAO,GAAG,CACtB,CAAC,MAAM,IAAI,CAAC,OAAO,QAAQ;;AAG9E,SAAgB,yBACd,QAIA;CACA,MAAM,YAAY,eAAe,OAAO;CACxC,MAAM,kBAAkB,sBAAsB,OAAO;AAErD,QAAO;EACL,WAAW,KAAK;AACd,UAAO,UAAU,WAAW,oBAAoB,IAAI,CAAC;;EAEvD,cAAc,UAAU,iBAAiB,MAAM;GAC7C,MAAM,WAAW,oBAAoB,SAAS;AAC9C,QAAK,MAAM,SAAS,iBAAiB;IACnC,MAAM,SAAS,wBAAwB,UAAU,MAAM,mBAAmB;AAC1E,QAAI,WAAW,MAAM;KACnB,IAAI,eAAe,mBAAmB;AACtC,SAAI,mBAAmB,MAAM;MAC3B,MAAM,cAAc,OAAO,MAAM;MACjC,MAAM,cAAc,oBAAoB,eAAe;MACvD,MAAM,sBAAsB,cACxB,wBAAwB,aAAa,YAAY,aAAa,GAC9D;AACJ,UAAI,wBAAwB,KAC1B,gBAAe;;AAGnB,YAAO;MAAE,GAAG;MAAO,eAAe,mBAAmB,cAAc,OAAO;MAAE;;;AAGhF,UAAO;;EAEV;;AAGH,SAAS,sBACP,QAC8B;CAC9B,MAAM,kBAAgD,EAAE;AACxD,MAAK,IAAI,aAAa,GAAG,aAAa,OAAO,QAAQ,cAAc;EACjE,MAAM,QAAQ,OAAO;AACrB,MAAI,CAAC,MAAM,MAAO;AAClB,OAAK,MAAM,CAAC,SAAS,eAAe,OAAO,QAAQ,MAAM,MAAM,EAAE;AAC/D,OAAI,CAAC,WAAW,WAAY;AAC5B,QAAK,MAAM,aAAa,WAAW,WACjC,iBAAgB,KAAK;IACnB,kBAAkB;IAClB;IACA,eAAe,UAAU;IACzB,oBAAoB,UAAU,cAAc,MAAM,IAAI,CAAC,OAAO,QAAQ;IACtE,kBAAkB,UAAU;IAC5B,MAAM,UAAU;IAChB,QAAQ,UAAU;IACnB,CAAC;;;AAIR,QAAO;;AAGT,SAAgB,wBACd,UACA,cAC0B;AAC1B,QAAO,kBAAkB,UAAU,aAAa;;AAGlD,SAAS,mBACP,cACA,cACmB;AACnB,QAAO,OAAO,OAAO,mBAAmB,EAAE,cAAc,aAAa"}
|
|
@@ -21,6 +21,10 @@ function isRouteSegmentFetchCache(value) {
|
|
|
21
21
|
return FETCH_CACHE_VALUES.has(value);
|
|
22
22
|
}
|
|
23
23
|
function resolveRevalidateSeconds(current, value) {
|
|
24
|
+
if (value === false) {
|
|
25
|
+
if (current === null) return Infinity;
|
|
26
|
+
return current === Infinity ? Infinity : current;
|
|
27
|
+
}
|
|
24
28
|
if (typeof value !== "number") return current;
|
|
25
29
|
if (current === null) return value;
|
|
26
30
|
return value < current ? value : current;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-segment-config.js","names":[],"sources":["../../src/server/app-segment-config.ts"],"sourcesContent":["import type { FetchCacheMode } from \"vinext/shims/fetch-cache\";\n\ntype AppRouteSegmentDynamic = \"auto\" | \"error\" | \"force-dynamic\" | \"force-static\";\n\ntype AppRouteSegmentConfigModule = {\n dynamic?: unknown;\n dynamicParams?: unknown;\n fetchCache?: unknown;\n revalidate?: unknown;\n};\n\ntype EffectiveAppPageSegmentConfig = {\n dynamicConfig?: AppRouteSegmentDynamic;\n dynamicParamsConfig?: boolean;\n fetchCache?: FetchCacheMode;\n revalidateSeconds: number | null;\n};\n\ntype ResolveAppPageSegmentConfigOptions = {\n layouts?: readonly (AppRouteSegmentConfigModule | null | undefined)[];\n page?: AppRouteSegmentConfigModule | null;\n};\n\nconst DYNAMIC_VALUES = new Set<unknown>([\"auto\", \"error\", \"force-dynamic\", \"force-static\"]);\nconst FETCH_CACHE_VALUES = new Set<unknown>([\n \"auto\",\n \"default-cache\",\n \"default-no-store\",\n \"force-cache\",\n \"force-no-store\",\n \"only-cache\",\n \"only-no-store\",\n]);\n\nfunction isRouteSegmentDynamic(value: unknown): value is AppRouteSegmentDynamic {\n return DYNAMIC_VALUES.has(value);\n}\n\nfunction isRouteSegmentFetchCache(value: unknown): value is FetchCacheMode {\n return FETCH_CACHE_VALUES.has(value);\n}\n\nfunction resolveRevalidateSeconds(current: number | null, value: unknown): number | null {\n //
|
|
1
|
+
{"version":3,"file":"app-segment-config.js","names":[],"sources":["../../src/server/app-segment-config.ts"],"sourcesContent":["import type { FetchCacheMode } from \"vinext/shims/fetch-cache\";\n\ntype AppRouteSegmentDynamic = \"auto\" | \"error\" | \"force-dynamic\" | \"force-static\";\n\ntype AppRouteSegmentConfigModule = {\n dynamic?: unknown;\n dynamicParams?: unknown;\n fetchCache?: unknown;\n revalidate?: unknown;\n};\n\ntype EffectiveAppPageSegmentConfig = {\n dynamicConfig?: AppRouteSegmentDynamic;\n dynamicParamsConfig?: boolean;\n fetchCache?: FetchCacheMode;\n revalidateSeconds: number | null;\n};\n\ntype ResolveAppPageSegmentConfigOptions = {\n layouts?: readonly (AppRouteSegmentConfigModule | null | undefined)[];\n page?: AppRouteSegmentConfigModule | null;\n};\n\nconst DYNAMIC_VALUES = new Set<unknown>([\"auto\", \"error\", \"force-dynamic\", \"force-static\"]);\nconst FETCH_CACHE_VALUES = new Set<unknown>([\n \"auto\",\n \"default-cache\",\n \"default-no-store\",\n \"force-cache\",\n \"force-no-store\",\n \"only-cache\",\n \"only-no-store\",\n]);\n\nfunction isRouteSegmentDynamic(value: unknown): value is AppRouteSegmentDynamic {\n return DYNAMIC_VALUES.has(value);\n}\n\nfunction isRouteSegmentFetchCache(value: unknown): value is FetchCacheMode {\n return FETCH_CACHE_VALUES.has(value);\n}\n\nfunction resolveRevalidateSeconds(current: number | null, value: unknown): number | null {\n // revalidate = false means \"cache indefinitely\" in Next.js segment config.\n // Represent it as Infinity so downstream code can distinguish \"never\n // revalidate\" (Infinity) from \"no config / unset\" (null).\n if (value === false) {\n if (current === null) return Infinity;\n // Shortest-wins: any finite interval is shorter than Infinity.\n return current === Infinity ? Infinity : current;\n }\n\n if (typeof value !== \"number\") {\n return current;\n }\n\n if (current === null) {\n return value;\n }\n\n return value < current ? value : current;\n}\n\nfunction isCacheFetchCacheMode(value: FetchCacheMode): boolean {\n return value === \"default-cache\" || value === \"force-cache\" || value === \"only-cache\";\n}\n\nfunction describeFetchCacheConflict(value: FetchCacheMode): string {\n return `Route segment config has incompatible fetchCache values including \"${value}\".`;\n}\n\n/**\n * Resolve the route segment config that applies to an App page route.\n *\n * Next.js collects config from every segment in the loader tree and reduces it\n * into the effective route config. The generated vinext entry already knows\n * the concrete layout/page modules for a route, so it should only describe\n * those modules and delegate the behavior to this helper.\n */\nexport function resolveAppPageSegmentConfig(\n options: ResolveAppPageSegmentConfigOptions,\n): EffectiveAppPageSegmentConfig {\n const segments = [...(options.layouts ?? []), options.page];\n // Reduction strategies differ by field:\n // - dynamic: child segments override parents.\n // - dynamicParams: false is sticky across the route tree.\n // - fetchCache: force/only modes take route-level precedence and reject conflicts.\n // - revalidate: the shortest numeric interval wins.\n const config: EffectiveAppPageSegmentConfig = {\n revalidateSeconds: null,\n };\n let hasForceCache = false;\n let hasForceNoStore = false;\n let hasOnlyCache = false;\n let hasOnlyNoStore = false;\n let hasParentDefaultNoStore = false;\n\n for (const segment of segments) {\n if (!segment) continue;\n\n if (isRouteSegmentDynamic(segment.dynamic)) {\n config.dynamicConfig = segment.dynamic;\n }\n\n if (segment.dynamicParams === false) {\n config.dynamicParamsConfig = false;\n } else if (segment.dynamicParams === true && config.dynamicParamsConfig !== false) {\n config.dynamicParamsConfig = true;\n }\n\n if (isRouteSegmentFetchCache(segment.fetchCache)) {\n const fetchCache = segment.fetchCache;\n\n if (hasParentDefaultNoStore && (fetchCache === \"auto\" || isCacheFetchCacheMode(fetchCache))) {\n throw new Error(describeFetchCacheConflict(fetchCache));\n }\n\n if (fetchCache === \"force-cache\") hasForceCache = true;\n if (fetchCache === \"force-no-store\") hasForceNoStore = true;\n if (fetchCache === \"only-cache\") hasOnlyCache = true;\n if (fetchCache === \"only-no-store\") hasOnlyNoStore = true;\n\n const hasCacheEnforcer = hasForceCache || hasOnlyCache;\n const hasNoStoreEnforcer = hasForceNoStore || hasOnlyNoStore;\n if (hasCacheEnforcer && hasNoStoreEnforcer) {\n throw new Error(describeFetchCacheConflict(fetchCache));\n }\n\n if (fetchCache === \"default-no-store\") {\n hasParentDefaultNoStore = true;\n }\n\n if (hasForceCache) {\n config.fetchCache = \"force-cache\";\n } else if (hasForceNoStore) {\n config.fetchCache = \"force-no-store\";\n } else if (hasOnlyCache) {\n config.fetchCache = \"only-cache\";\n } else if (hasOnlyNoStore) {\n config.fetchCache = \"only-no-store\";\n } else {\n config.fetchCache = fetchCache;\n }\n }\n\n config.revalidateSeconds = resolveRevalidateSeconds(\n config.revalidateSeconds,\n segment.revalidate,\n );\n }\n\n if (config.dynamicConfig === \"force-dynamic\") {\n config.revalidateSeconds = 0;\n }\n\n // Top-level dynamic modes supply fetchCache defaults unless a segment does.\n if (config.fetchCache === undefined) {\n if (config.dynamicConfig === \"force-dynamic\") {\n config.fetchCache = \"force-no-store\";\n } else if (config.dynamicConfig === \"error\") {\n config.fetchCache = \"only-cache\";\n }\n }\n\n // Static-only dynamic modes change the default, but explicit dynamicParams wins.\n if (\n config.dynamicParamsConfig === undefined &&\n (config.dynamicConfig === \"error\" || config.dynamicConfig === \"force-static\")\n ) {\n config.dynamicParamsConfig = false;\n }\n\n return config;\n}\n\nexport function resolveAppPageFetchCacheMode(\n options: ResolveAppPageSegmentConfigOptions,\n): FetchCacheMode | null {\n return resolveAppPageSegmentConfig(options).fetchCache ?? null;\n}\n"],"mappings":";AAuBA,MAAM,iBAAiB,IAAI,IAAa;CAAC;CAAQ;CAAS;CAAiB;CAAe,CAAC;AAC3F,MAAM,qBAAqB,IAAI,IAAa;CAC1C;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AAEF,SAAS,sBAAsB,OAAiD;AAC9E,QAAO,eAAe,IAAI,MAAM;;AAGlC,SAAS,yBAAyB,OAAyC;AACzE,QAAO,mBAAmB,IAAI,MAAM;;AAGtC,SAAS,yBAAyB,SAAwB,OAA+B;AAIvF,KAAI,UAAU,OAAO;AACnB,MAAI,YAAY,KAAM,QAAO;AAE7B,SAAO,YAAY,WAAW,WAAW;;AAG3C,KAAI,OAAO,UAAU,SACnB,QAAO;AAGT,KAAI,YAAY,KACd,QAAO;AAGT,QAAO,QAAQ,UAAU,QAAQ;;AAGnC,SAAS,sBAAsB,OAAgC;AAC7D,QAAO,UAAU,mBAAmB,UAAU,iBAAiB,UAAU;;AAG3E,SAAS,2BAA2B,OAA+B;AACjE,QAAO,sEAAsE,MAAM;;;;;;;;;;AAWrF,SAAgB,4BACd,SAC+B;CAC/B,MAAM,WAAW,CAAC,GAAI,QAAQ,WAAW,EAAE,EAAG,QAAQ,KAAK;CAM3D,MAAM,SAAwC,EAC5C,mBAAmB,MACpB;CACD,IAAI,gBAAgB;CACpB,IAAI,kBAAkB;CACtB,IAAI,eAAe;CACnB,IAAI,iBAAiB;CACrB,IAAI,0BAA0B;AAE9B,MAAK,MAAM,WAAW,UAAU;AAC9B,MAAI,CAAC,QAAS;AAEd,MAAI,sBAAsB,QAAQ,QAAQ,CACxC,QAAO,gBAAgB,QAAQ;AAGjC,MAAI,QAAQ,kBAAkB,MAC5B,QAAO,sBAAsB;WACpB,QAAQ,kBAAkB,QAAQ,OAAO,wBAAwB,MAC1E,QAAO,sBAAsB;AAG/B,MAAI,yBAAyB,QAAQ,WAAW,EAAE;GAChD,MAAM,aAAa,QAAQ;AAE3B,OAAI,4BAA4B,eAAe,UAAU,sBAAsB,WAAW,EACxF,OAAM,IAAI,MAAM,2BAA2B,WAAW,CAAC;AAGzD,OAAI,eAAe,cAAe,iBAAgB;AAClD,OAAI,eAAe,iBAAkB,mBAAkB;AACvD,OAAI,eAAe,aAAc,gBAAe;AAChD,OAAI,eAAe,gBAAiB,kBAAiB;AAIrD,QAFyB,iBAAiB,kBACf,mBAAmB,gBAE5C,OAAM,IAAI,MAAM,2BAA2B,WAAW,CAAC;AAGzD,OAAI,eAAe,mBACjB,2BAA0B;AAG5B,OAAI,cACF,QAAO,aAAa;YACX,gBACT,QAAO,aAAa;YACX,aACT,QAAO,aAAa;YACX,eACT,QAAO,aAAa;OAEpB,QAAO,aAAa;;AAIxB,SAAO,oBAAoB,yBACzB,OAAO,mBACP,QAAQ,WACT;;AAGH,KAAI,OAAO,kBAAkB,gBAC3B,QAAO,oBAAoB;AAI7B,KAAI,OAAO,eAAe,KAAA;MACpB,OAAO,kBAAkB,gBAC3B,QAAO,aAAa;WACX,OAAO,kBAAkB,QAClC,QAAO,aAAa;;AAKxB,KACE,OAAO,wBAAwB,KAAA,MAC9B,OAAO,kBAAkB,WAAW,OAAO,kBAAkB,gBAE9D,QAAO,sBAAsB;AAG/B,QAAO;;AAGT,SAAgB,6BACd,SACuB;AACvB,QAAO,4BAA4B,QAAQ,CAAC,cAAc"}
|
|
@@ -1,9 +1,18 @@
|
|
|
1
|
+
import { internalServerErrorResponse, payloadTooLargeResponse } from "./http-error-responses.js";
|
|
1
2
|
import { validateCsrfOrigin, validateServerActionPayload } from "./request-pipeline.js";
|
|
2
3
|
import { setCurrentFetchCacheMode } from "../shims/fetch-cache.js";
|
|
4
|
+
import { VINEXT_RSC_VARY_HEADER } from "./app-rsc-cache-busting.js";
|
|
3
5
|
import { createServerActionNotFoundResponse, getServerActionNotFoundMessage, isServerActionNotFoundError } from "./server-action-not-found.js";
|
|
4
6
|
import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
|
|
7
|
+
import { readStreamAsTextWithLimit } from "../utils/text-stream.js";
|
|
8
|
+
import { getNextErrorDigest, parseNextHttpErrorDigest, parseNextRedirectDigest } from "./next-error-digest.js";
|
|
5
9
|
import { resolveAppPageActionRerenderTarget } from "./app-page-request.js";
|
|
6
10
|
//#region src/server/app-server-action-execution.ts
|
|
11
|
+
/**
|
|
12
|
+
* Matches Next.js' server action argument cap to prevent stack overflow in
|
|
13
|
+
* Function.prototype.apply when decoding hostile action payloads.
|
|
14
|
+
*/
|
|
15
|
+
const SERVER_ACTION_ARGS_LIMIT = 1e3;
|
|
7
16
|
function isRequestBodyTooLarge(error) {
|
|
8
17
|
return error instanceof Error && error.message === "Request body too large";
|
|
9
18
|
}
|
|
@@ -16,24 +25,14 @@ function normalizeError(error) {
|
|
|
16
25
|
function getServerActionFailureMessage(error) {
|
|
17
26
|
return error instanceof Error && error.message ? error.message : String(error);
|
|
18
27
|
}
|
|
28
|
+
function validateServerActionArgs(args) {
|
|
29
|
+
if (args.length > SERVER_ACTION_ARGS_LIMIT) throw new Error(`Server Action arguments list is too long (${args.length}). Maximum allowed is ${SERVER_ACTION_ARGS_LIMIT}.`);
|
|
30
|
+
}
|
|
19
31
|
async function readActionBodyWithLimit(request, maxBytes) {
|
|
20
32
|
if (!request.body) return "";
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
let totalSize = 0;
|
|
25
|
-
for (;;) {
|
|
26
|
-
const result = await reader.read();
|
|
27
|
-
if (result.done) break;
|
|
28
|
-
totalSize += result.value.byteLength;
|
|
29
|
-
if (totalSize > maxBytes) {
|
|
30
|
-
await reader.cancel();
|
|
31
|
-
throw new Error("Request body too large");
|
|
32
|
-
}
|
|
33
|
-
chunks.push(decoder.decode(result.value, { stream: true }));
|
|
34
|
-
}
|
|
35
|
-
chunks.push(decoder.decode());
|
|
36
|
-
return chunks.join("");
|
|
33
|
+
return readStreamAsTextWithLimit(request.body, maxBytes, () => {
|
|
34
|
+
throw new Error("Request body too large");
|
|
35
|
+
});
|
|
37
36
|
}
|
|
38
37
|
async function readActionFormDataWithLimit(request, maxBytes) {
|
|
39
38
|
if (!request.body) return new FormData();
|
|
@@ -58,46 +57,38 @@ async function readActionFormDataWithLimit(request, maxBytes) {
|
|
|
58
57
|
}
|
|
59
58
|
return new Response(combined, { headers: { "Content-Type": request.headers.get("content-type") || "" } }).formData();
|
|
60
59
|
}
|
|
61
|
-
function getErrorDigest(error) {
|
|
62
|
-
if (!error || typeof error !== "object" || !("digest" in error)) return null;
|
|
63
|
-
return String(error.digest);
|
|
64
|
-
}
|
|
65
60
|
function getActionControlResponse(error) {
|
|
66
|
-
const digest =
|
|
61
|
+
const digest = getNextErrorDigest(error);
|
|
67
62
|
if (!digest) return null;
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
if (digest === "NEXT_NOT_FOUND" || digest.startsWith("NEXT_HTTP_ERROR_FALLBACK;")) {
|
|
77
|
-
const statusCode = digest === "NEXT_NOT_FOUND" ? 404 : parseInt(digest.split(";")[1], 10);
|
|
78
|
-
if (!Number.isInteger(statusCode)) return null;
|
|
63
|
+
const redirect = parseNextRedirectDigest(digest);
|
|
64
|
+
if (redirect) return {
|
|
65
|
+
kind: "redirect",
|
|
66
|
+
url: redirect.url
|
|
67
|
+
};
|
|
68
|
+
const httpError = parseNextHttpErrorDigest(digest);
|
|
69
|
+
if (httpError) {
|
|
70
|
+
if (!Number.isInteger(httpError.status)) return null;
|
|
79
71
|
return {
|
|
80
72
|
kind: "status",
|
|
81
|
-
statusCode
|
|
73
|
+
statusCode: httpError.status
|
|
82
74
|
};
|
|
83
75
|
}
|
|
84
76
|
return null;
|
|
85
77
|
}
|
|
86
78
|
function getActionRedirect(error) {
|
|
87
|
-
const digest =
|
|
88
|
-
if (!digest
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
if (!encodedUrl) return null;
|
|
79
|
+
const digest = getNextErrorDigest(error);
|
|
80
|
+
if (!digest) return null;
|
|
81
|
+
const redirect = parseNextRedirectDigest(digest);
|
|
82
|
+
if (!redirect) return null;
|
|
92
83
|
return {
|
|
93
|
-
status:
|
|
94
|
-
type:
|
|
95
|
-
url:
|
|
84
|
+
status: redirect.status,
|
|
85
|
+
type: redirect.type,
|
|
86
|
+
url: redirect.url
|
|
96
87
|
};
|
|
97
88
|
}
|
|
98
89
|
function isActionHttpFallback(error) {
|
|
99
|
-
const digest =
|
|
100
|
-
return digest
|
|
90
|
+
const digest = getNextErrorDigest(error);
|
|
91
|
+
return digest !== null && parseNextHttpErrorDigest(digest) !== null;
|
|
101
92
|
}
|
|
102
93
|
function createServerActionErrorResponse(error, options) {
|
|
103
94
|
options.getAndClearPendingCookies();
|
|
@@ -112,7 +103,7 @@ function createServerActionErrorResponse(error, options) {
|
|
|
112
103
|
routeType: "action"
|
|
113
104
|
});
|
|
114
105
|
options.clearRequestContext();
|
|
115
|
-
return
|
|
106
|
+
return internalServerErrorResponse(process.env.NODE_ENV === "production" ? void 0 : "Server action failed: " + getServerActionFailureMessage(error));
|
|
116
107
|
}
|
|
117
108
|
function createActionNotFoundResponse(actionId, options) {
|
|
118
109
|
options.getAndClearPendingCookies();
|
|
@@ -129,7 +120,7 @@ async function handleProgressiveServerActionRequest(options) {
|
|
|
129
120
|
if (csrfResponse) return csrfResponse;
|
|
130
121
|
if (parseInt(options.request.headers.get("content-length") || "0", 10) > options.maxActionBodySize) {
|
|
131
122
|
options.clearRequestContext();
|
|
132
|
-
return
|
|
123
|
+
return payloadTooLargeResponse();
|
|
133
124
|
}
|
|
134
125
|
try {
|
|
135
126
|
let body;
|
|
@@ -138,7 +129,7 @@ async function handleProgressiveServerActionRequest(options) {
|
|
|
138
129
|
} catch (error) {
|
|
139
130
|
if (isRequestBodyTooLarge(error)) {
|
|
140
131
|
options.clearRequestContext();
|
|
141
|
-
return
|
|
132
|
+
return payloadTooLargeResponse();
|
|
142
133
|
}
|
|
143
134
|
throw error;
|
|
144
135
|
}
|
|
@@ -189,7 +180,7 @@ async function handleProgressiveServerActionRequest(options) {
|
|
|
189
180
|
routeType: "action"
|
|
190
181
|
});
|
|
191
182
|
options.clearRequestContext();
|
|
192
|
-
return
|
|
183
|
+
return internalServerErrorResponse(process.env.NODE_ENV === "production" ? void 0 : "Server action failed: " + getServerActionFailureMessage(error));
|
|
193
184
|
}
|
|
194
185
|
}
|
|
195
186
|
async function handleServerActionRscRequest(options) {
|
|
@@ -198,7 +189,7 @@ async function handleServerActionRscRequest(options) {
|
|
|
198
189
|
if (csrfResponse) return csrfResponse;
|
|
199
190
|
if (parseInt(options.request.headers.get("content-length") || "0", 10) > options.maxActionBodySize) {
|
|
200
191
|
options.clearRequestContext();
|
|
201
|
-
return
|
|
192
|
+
return payloadTooLargeResponse();
|
|
202
193
|
}
|
|
203
194
|
try {
|
|
204
195
|
let body;
|
|
@@ -207,7 +198,7 @@ async function handleServerActionRscRequest(options) {
|
|
|
207
198
|
} catch (error) {
|
|
208
199
|
if (isRequestBodyTooLarge(error)) {
|
|
209
200
|
options.clearRequestContext();
|
|
210
|
-
return
|
|
201
|
+
return payloadTooLargeResponse();
|
|
211
202
|
}
|
|
212
203
|
throw error;
|
|
213
204
|
}
|
|
@@ -237,6 +228,7 @@ async function handleServerActionRscRequest(options) {
|
|
|
237
228
|
const previousHeadersPhase = options.setHeadersAccessPhase("action");
|
|
238
229
|
try {
|
|
239
230
|
try {
|
|
231
|
+
validateServerActionArgs(args);
|
|
240
232
|
returnValue = {
|
|
241
233
|
ok: true,
|
|
242
234
|
data: await action.apply(null, args)
|
|
@@ -268,7 +260,7 @@ async function handleServerActionRscRequest(options) {
|
|
|
268
260
|
options.clearRequestContext();
|
|
269
261
|
const redirectHeaders = new Headers({
|
|
270
262
|
"Content-Type": "text/x-component; charset=utf-8",
|
|
271
|
-
Vary:
|
|
263
|
+
Vary: VINEXT_RSC_VARY_HEADER
|
|
272
264
|
});
|
|
273
265
|
mergeMiddlewareResponseHeaders(redirectHeaders, options.middlewareHeaders);
|
|
274
266
|
redirectHeaders.set("x-action-redirect", actionRedirect.url);
|
|
@@ -329,7 +321,7 @@ async function handleServerActionRscRequest(options) {
|
|
|
329
321
|
const actionDraftCookie = options.getDraftModeCookieHeader();
|
|
330
322
|
const actionHeaders = new Headers({
|
|
331
323
|
"Content-Type": "text/x-component; charset=utf-8",
|
|
332
|
-
Vary:
|
|
324
|
+
Vary: VINEXT_RSC_VARY_HEADER
|
|
333
325
|
});
|
|
334
326
|
mergeMiddlewareResponseHeaders(actionHeaders, options.middlewareHeaders);
|
|
335
327
|
const actionResponse = new Response(rscStream, {
|