vinext 1.2.0 → 1.3.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 +13 -10
- package/dist/build/client-build-config.d.ts +64 -3
- package/dist/build/client-build-config.js +131 -4
- package/dist/build/client-reference-groups.d.ts +163 -0
- package/dist/build/client-reference-groups.js +534 -0
- package/dist/build/module-dependency-cache.d.ts +31 -0
- package/dist/build/module-dependency-cache.js +51 -1
- package/dist/build/next-client-runtime-manifests.d.ts +10 -1
- package/dist/build/next-client-runtime-manifests.js +19 -4
- package/dist/build/nitro-public-files.d.ts +24 -0
- package/dist/build/nitro-public-files.js +60 -0
- package/dist/build/output-root-externals.d.ts +21 -0
- package/dist/build/output-root-externals.js +40 -0
- package/dist/build/pages-client-assets-module.js +1 -1
- package/dist/build/prerender-paths.js +6 -3
- package/dist/build/prerender.js +1 -1
- package/dist/build/server-actions-encryption-key.d.ts +23 -0
- package/dist/build/server-actions-encryption-key.js +101 -0
- package/dist/build/ssr-manifest.d.ts +3 -0
- package/dist/build/ssr-manifest.js +10 -1
- package/dist/check.js +5 -6
- package/dist/cli-dev-config.js +3 -3
- package/dist/cli.js +1 -1
- package/dist/client/client-rewrite-params.d.ts +9 -0
- package/dist/client/client-rewrite-params.js +20 -0
- package/dist/client/dev-error-overlay.js +2 -1
- package/dist/client/navigation-runtime.d.ts +25 -2
- package/dist/client/navigation-runtime.js +42 -11
- package/dist/client/vinext-next-data.d.ts +0 -1
- package/dist/config/config-matchers.d.ts +15 -40
- package/dist/config/config-matchers.js +195 -262
- package/dist/config/config-source.d.ts +34 -0
- package/dist/config/config-source.js +141 -0
- package/dist/config/header-params.d.ts +29 -0
- package/dist/config/header-params.js +106 -0
- package/dist/config/next-config.d.ts +7 -5
- package/dist/config/next-config.js +120 -7
- package/dist/entries/app-browser-entry.d.ts +14 -1
- package/dist/entries/app-browser-entry.js +26 -36
- package/dist/entries/app-rsc-entry.d.ts +2 -0
- package/dist/entries/app-rsc-entry.js +92 -57
- package/dist/entries/app-rsc-manifest.d.ts +10 -0
- package/dist/entries/app-rsc-manifest.js +20 -1
- package/dist/entries/app-ssr-entry.d.ts +4 -1
- package/dist/entries/app-ssr-entry.js +9 -2
- package/dist/entries/pages-client-entry.d.ts +1 -0
- package/dist/entries/pages-client-entry.js +6 -6
- package/dist/entries/pages-server-entry.js +17 -14
- package/dist/index.d.ts +11 -0
- package/dist/index.js +350 -175
- package/dist/init.d.ts +1 -1
- package/dist/init.js +103 -6
- package/dist/plugins/ast-utils.d.ts +53 -2
- package/dist/plugins/ast-utils.js +90 -2
- package/dist/plugins/cloudflare-dev-module-urls.d.ts +41 -0
- package/dist/plugins/cloudflare-dev-module-urls.js +271 -0
- package/dist/plugins/commonjs-esm-facade.js +2 -2
- package/dist/plugins/css-module-imports.js +13 -20
- package/dist/plugins/dynamic-preload-metadata.js +2 -3
- package/dist/plugins/extensionless-dynamic-import.js +2 -3
- package/dist/plugins/fonts.d.ts +1 -1
- package/dist/plugins/fonts.js +3 -3
- package/dist/plugins/ignore-dynamic-requests.js +2 -3
- package/dist/plugins/import-meta-url.js +3 -4
- package/dist/plugins/instrumentation-client.js +3 -2
- package/dist/plugins/middleware-export-validation.js +2 -3
- package/dist/plugins/og-harfbuzz.js +2 -3
- package/dist/plugins/optimize-imports.d.ts +25 -2
- package/dist/plugins/optimize-imports.js +109 -24
- package/dist/plugins/pages-node-externals.js +2 -3
- package/dist/plugins/remove-console.js +2 -18
- package/dist/plugins/require-condition-resolution.js +3 -3
- package/dist/plugins/require-context.js +2 -3
- package/dist/plugins/rsc-client-reference-loaders.d.ts +45 -1
- package/dist/plugins/rsc-client-reference-loaders.js +336 -18
- package/dist/plugins/strip-server-exports.js +3 -4
- package/dist/plugins/styled-jsx.js +2 -3
- package/dist/plugins/use-cache-callable.d.ts +26 -2
- package/dist/plugins/use-cache-callable.js +101 -36
- package/dist/plugins/worker-image-imports.d.ts +1 -0
- package/dist/plugins/worker-image-imports.js +31 -34
- package/dist/plugins/worker-use-server.js +38 -14
- package/dist/routing/app-route-graph.d.ts +1 -1
- package/dist/routing/browser-route-manifest.d.ts +43 -0
- package/dist/routing/browser-route-manifest.js +195 -0
- package/dist/routing/hashed-route-patterns.d.ts +4 -0
- package/dist/routing/hashed-route-patterns.js +22 -0
- package/dist/routing/optimistic-route-trie.d.ts +27 -0
- package/dist/routing/optimistic-route-trie.js +102 -0
- package/dist/routing/route-validation.d.ts +6 -1
- package/dist/routing/route-validation.js +26 -10
- package/dist/server/api-handler.js +1 -1
- package/dist/server/app-action-forwarding.d.ts +8 -0
- package/dist/server/app-action-forwarding.js +17 -3
- package/dist/server/app-browser-entry.js +149 -62
- package/dist/server/app-browser-error.d.ts +3 -1
- package/dist/server/app-browser-error.js +7 -2
- package/dist/server/app-browser-interception-context.d.ts +2 -2
- package/dist/server/app-browser-interception-context.js +1 -1
- package/dist/server/app-browser-mpa-navigation.d.ts +1 -0
- package/dist/server/app-browser-mpa-navigation.js +6 -5
- package/dist/server/app-browser-navigation-controller.d.ts +17 -6
- package/dist/server/app-browser-navigation-controller.js +88 -26
- package/dist/server/app-browser-prefetch-response.js +2 -2
- package/dist/server/app-browser-state.d.ts +2 -2
- package/dist/server/app-browser-state.js +1 -1
- package/dist/server/app-browser-supplemental-refresh.js +1 -1
- package/dist/server/app-browser-visible-commit.d.ts +4 -4
- package/dist/server/app-client-reference-preloader.d.ts +23 -0
- package/dist/server/app-client-reference-preloader.js +30 -7
- package/dist/server/app-fallback-renderer.js +2 -1
- package/dist/server/app-middleware.d.ts +6 -0
- package/dist/server/app-middleware.js +8 -10
- package/dist/server/app-optimistic-routing.d.ts +8 -10
- package/dist/server/app-optimistic-routing.js +4 -95
- package/dist/server/app-page-boundary-render.js +8 -1
- package/dist/server/app-page-cache-render.js +1 -0
- package/dist/server/app-page-dispatch.js +3 -1
- package/dist/server/app-page-render.js +4 -2
- package/dist/server/app-page-rsc-render-status.d.ts +1 -0
- package/dist/server/app-page-rsc-render-status.js +1 -0
- package/dist/server/app-page-search-params-observation.d.ts +1 -4
- package/dist/server/app-page-search-params-observation.js +8 -10
- package/dist/server/app-page-stream.d.ts +7 -0
- package/dist/server/app-page-stream.js +1 -0
- package/dist/server/app-pages-bridge.d.ts +2 -1
- package/dist/server/app-pages-bridge.js +12 -8
- package/dist/server/app-prerender-endpoints.js +1 -1
- package/dist/server/app-prerender-static-params.js +3 -2
- package/dist/server/app-render-abort-error.d.ts +19 -0
- package/dist/server/app-render-abort-error.js +31 -1
- package/dist/server/app-render-dependency.js +42 -2
- package/dist/server/app-request-stage-independent-entry.js +7 -7
- package/dist/server/app-response-stage-entry.js +5 -5
- package/dist/server/app-route-handler-dispatch.js +3 -1
- package/dist/server/app-route-handler-execution.d.ts +2 -0
- package/dist/server/app-route-handler-execution.js +9 -2
- package/dist/server/app-route-handler-middleware-context.d.ts +2 -1
- package/dist/server/app-route-handler-middleware-context.js +3 -3
- package/dist/server/app-route-handler-response.d.ts +2 -1
- package/dist/server/app-route-handler-response.js +2 -2
- package/dist/server/app-route-handler-runtime.d.ts +2 -0
- package/dist/server/app-route-handler-runtime.js +21 -4
- package/dist/server/app-route-module-loader.js +7 -6
- package/dist/server/app-route-tree.d.ts +20 -0
- package/dist/server/app-route-tree.js +18 -0
- package/dist/server/app-router-entry.js +7 -7
- package/dist/server/app-rsc-cache-busting.d.ts +16 -0
- package/dist/server/app-rsc-cache-busting.js +29 -12
- package/dist/server/app-rsc-combined-handler.js +8 -1
- package/dist/server/app-rsc-errors.d.ts +7 -0
- package/dist/server/app-rsc-errors.js +9 -2
- package/dist/server/app-rsc-handler.d.ts +4 -1
- package/dist/server/app-rsc-handler.js +151 -135
- package/dist/server/app-rsc-request-normalization.js +3 -3
- package/dist/server/app-rsc-response-finalizer.d.ts +5 -0
- package/dist/server/app-rsc-response-finalizer.js +4 -1
- package/dist/server/app-rsc-response-stage.js +5 -3
- package/dist/server/app-rsc-route-matching.d.ts +1 -0
- package/dist/server/app-rsc-route-matching.js +1 -1
- package/dist/server/app-server-action-execution.d.ts +23 -6
- package/dist/server/app-server-action-execution.js +51 -57
- package/dist/server/app-ssr-entry.d.ts +6 -0
- package/dist/server/app-ssr-entry.js +21 -11
- package/dist/server/app-ssr-stream.d.ts +7 -0
- package/dist/server/app-ssr-stream.js +13 -1
- package/dist/server/app-visited-response-cache.js +2 -2
- package/dist/server/config-headers.js +13 -4
- package/dist/server/defer-until-stream-consumed.d.ts +2 -1
- package/dist/server/defer-until-stream-consumed.js +3 -1
- package/dist/server/dev-server.js +1 -1
- package/dist/server/image-optimization.js +1 -0
- package/dist/server/isolate-shared-promise.d.ts +10 -0
- package/dist/server/isolate-shared-promise.js +33 -0
- package/dist/server/isr-cache.js +3 -2
- package/dist/server/metadata-route-response.js +2 -2
- package/dist/server/middleware-matcher-pattern.d.ts +0 -1
- package/dist/server/middleware-matcher-pattern.js +11 -140
- package/dist/server/middleware-matcher.js +5 -6
- package/dist/server/middleware-response-headers.d.ts +31 -0
- package/dist/server/middleware-response-headers.js +57 -1
- package/dist/server/middleware-runtime.js +30 -17
- package/dist/server/navigation-planner.d.ts +2 -2
- package/dist/server/navigation-planner.js +1 -1
- package/dist/server/nitro-public-files-plugin.d.ts +38 -0
- package/dist/server/nitro-public-files-plugin.js +106 -0
- package/dist/server/nitro-public-files.d.ts +21 -0
- package/dist/server/nitro-public-files.js +39 -0
- package/dist/server/open-redirect.d.ts +11 -4
- package/dist/server/open-redirect.js +11 -4
- package/dist/server/pages-api-route.js +2 -2
- package/dist/server/pages-asset-tags.d.ts +5 -0
- package/dist/server/pages-asset-tags.js +9 -2
- package/dist/server/pages-client-assets.d.ts +4 -1
- package/dist/server/pages-data-route.js +2 -1
- package/dist/server/pages-i18n.d.ts +18 -0
- package/dist/server/pages-i18n.js +18 -2
- package/dist/server/pages-node-compat.d.ts +5 -3
- package/dist/server/pages-node-compat.js +35 -16
- package/dist/server/pages-page-data.js +1 -1
- package/dist/server/pages-page-handler.js +1 -1
- package/dist/server/pages-page-response.js +1 -1
- package/dist/server/pages-request-pipeline.d.ts +6 -1
- package/dist/server/pages-request-pipeline.js +35 -39
- package/dist/server/pages-request-stage-entry.js +20 -10
- package/dist/server/pages-response-stage-entry.js +1 -1
- package/dist/server/pages-revalidate.js +3 -2
- package/dist/server/pages-router-entry.js +2 -2
- package/dist/server/prod-server.d.ts +2 -2
- package/dist/server/prod-server.js +74 -36
- package/dist/server/proxy-trust.d.ts +6 -0
- package/dist/server/proxy-trust.js +12 -6
- package/dist/server/request-pipeline.d.ts +5 -0
- package/dist/server/request-pipeline.js +12 -1
- package/dist/server/rsc-stream-hints.d.ts +1 -1
- package/dist/server/rsc-stream-hints.js +21 -3
- package/dist/server/server-reference-loader.js +10 -1
- package/dist/server/static-file-cache.js +15 -3
- package/dist/server/worker-image-optimization.js +19 -6
- package/dist/server/worker-utils.js +1 -1
- package/dist/shims/cache-handler.js +3 -2
- package/dist/shims/cache-request-state.d.ts +40 -3
- package/dist/shims/cache-request-state.js +70 -5
- package/dist/shims/cache-runtime.js +47 -19
- package/dist/shims/cache.d.ts +2 -2
- package/dist/shims/cache.js +17 -8
- package/dist/shims/cdn-purge-routes.d.ts +24 -0
- package/dist/shims/cdn-purge-routes.js +77 -0
- package/dist/shims/dynamic.js +17 -4
- package/dist/shims/form.js +8 -3
- package/dist/shims/head.js +1 -1
- package/dist/shims/headers.js +2 -2
- package/dist/shims/image-props.d.ts +93 -0
- package/dist/shims/image-props.js +323 -0
- package/dist/shims/image.d.ts +4 -18
- package/dist/shims/image.js +4 -319
- package/dist/shims/internal/headers-state.d.ts +7 -0
- package/dist/shims/internal/headers-state.js +14 -2
- package/dist/shims/internal/hybrid-client-route-owner-direct.d.ts +4 -1
- package/dist/shims/internal/hybrid-client-route-owner-direct.js +32 -15
- package/dist/shims/internal/hybrid-client-route-owner.js +9 -8
- package/dist/shims/link-prefetch.js +5 -4
- package/dist/shims/link.js +7 -5
- package/dist/shims/navigation.d.ts +1 -1
- package/dist/shims/navigation.js +21 -10
- package/dist/shims/og.js +35 -10
- package/dist/shims/request-context.d.ts +13 -0
- package/dist/shims/router.js +28 -52
- package/dist/shims/server.d.ts +42 -8
- package/dist/shims/server.js +99 -15
- package/dist/shims/thenable-params.d.ts +6 -1
- package/dist/shims/thenable-params.js +11 -2
- package/dist/shims/unified-request-context.d.ts +5 -0
- package/dist/shims/unified-request-context.js +2 -0
- package/dist/shims/url-utils.d.ts +7 -0
- package/dist/shims/url-utils.js +12 -3
- package/dist/utils/asset-prefix.d.ts +7 -0
- package/dist/utils/asset-prefix.js +10 -1
- package/dist/utils/client-build-manifest.js +12 -5
- package/dist/utils/client-runtime-metadata.d.ts +1 -0
- package/dist/utils/client-runtime-metadata.js +15 -2
- package/dist/utils/domain-locale.js +1 -1
- package/dist/utils/lazy-chunks.d.ts +4 -0
- package/dist/utils/manifest-paths.d.ts +14 -0
- package/dist/utils/manifest-paths.js +22 -1
- package/dist/utils/path-to-regexp.d.ts +21 -0
- package/dist/{server/middleware-path-to-regexp.js → utils/path-to-regexp.js} +14 -11
- package/dist/utils/plugin-react-version.d.ts +15 -0
- package/dist/utils/plugin-react-version.js +64 -0
- package/dist/utils/plugin-rsc-version.d.ts +2 -0
- package/dist/utils/plugin-rsc-version.js +28 -2
- package/dist/utils/public-routes.d.ts +2 -0
- package/dist/utils/public-routes.js +18 -7
- package/dist/utils/react-version.d.ts +7 -0
- package/dist/utils/react-version.js +39 -16
- package/package.json +6 -6
- package/dist/build/nitro-route-rules.d.ts +0 -47
- package/dist/build/nitro-route-rules.js +0 -79
- package/dist/plugins/cache-flight-codec.d.ts +0 -19
- package/dist/plugins/cache-flight-codec.js +0 -68
- package/dist/server/middleware-path-to-regexp.d.ts +0 -13
- package/dist/utils/regex-safety.d.ts +0 -17
- package/dist/utils/regex-safety.js +0 -789
|
@@ -11,7 +11,7 @@ export declare function isOpenRedirectShaped(rawPathname: string): boolean;
|
|
|
11
11
|
/**
|
|
12
12
|
* What a request entry answers for a raw path containing a backslash or a
|
|
13
13
|
* repeated slash: Next.js's 308, or a 404 when the collapsed path would still
|
|
14
|
-
* be open-redirect shaped.
|
|
14
|
+
* be open-redirect shaped or the raw target is not origin-form.
|
|
15
15
|
*/
|
|
16
16
|
export type RepeatedSlashRedirect = {
|
|
17
17
|
status: 308;
|
|
@@ -33,17 +33,24 @@ export type RepeatedSlashRedirect = {
|
|
|
33
33
|
* `//evil.com` → `/evil.com`. Percent-encoded `%2F`/`%5C` are not touched and
|
|
34
34
|
* keep falling through to `isOpenRedirectShaped` (404), as in Next.js.
|
|
35
35
|
*
|
|
36
|
-
* The Location is always same-origin.
|
|
37
|
-
* (`GET http://host//x`) are left alone. A collapsed path that still starts
|
|
36
|
+
* The Location is always same-origin. A collapsed path that still starts
|
|
38
37
|
* with an encoded slash or backslash (`//%2Fevil.com`, `/.//%2Fevil.com`) is
|
|
39
38
|
* never echoed into a Location or routed: it gets a 404 instead.
|
|
40
39
|
*
|
|
40
|
+
* A raw Node request target that is not origin-form (`GET http://evil.example/x`,
|
|
41
|
+
* which Node's parser accepts, or `OPTIONS *`) also gets a 404. Next.js never
|
|
42
|
+
* routes these either: it 308s absolute-form targets to their own URL (the
|
|
43
|
+
* `//` after the scheme trips the same check) and 500s `OPTIONS *`. Routing
|
|
44
|
+
* them would let the request line choose the origin of `request.url` that
|
|
45
|
+
* middleware and handlers see, bypassing the Host trust policy. Request-based
|
|
46
|
+
* entries always pass a pathname.
|
|
47
|
+
*
|
|
41
48
|
* @param rawUrl - The raw request target: pathname plus optional `?query`
|
|
42
49
|
*/
|
|
43
50
|
export declare function getRepeatedSlashRedirect(rawUrl: string): RepeatedSlashRedirect | null;
|
|
44
51
|
/**
|
|
45
52
|
* Build the Response for a raw request path containing a backslash or a
|
|
46
|
-
* repeated slash. See `getRepeatedSlashRedirect`.
|
|
53
|
+
* repeated slash, or a non-origin-form target. See `getRepeatedSlashRedirect`.
|
|
47
54
|
*/
|
|
48
55
|
export declare function repeatedSlashRedirectResponse(rawUrl: string): Response | null;
|
|
49
56
|
/**
|
|
@@ -34,15 +34,22 @@ const REDIRECT_LOCATION_BASE = "http://vinext.invalid";
|
|
|
34
34
|
* `//evil.com` → `/evil.com`. Percent-encoded `%2F`/`%5C` are not touched and
|
|
35
35
|
* keep falling through to `isOpenRedirectShaped` (404), as in Next.js.
|
|
36
36
|
*
|
|
37
|
-
* The Location is always same-origin.
|
|
38
|
-
* (`GET http://host//x`) are left alone. A collapsed path that still starts
|
|
37
|
+
* The Location is always same-origin. A collapsed path that still starts
|
|
39
38
|
* with an encoded slash or backslash (`//%2Fevil.com`, `/.//%2Fevil.com`) is
|
|
40
39
|
* never echoed into a Location or routed: it gets a 404 instead.
|
|
41
40
|
*
|
|
41
|
+
* A raw Node request target that is not origin-form (`GET http://evil.example/x`,
|
|
42
|
+
* which Node's parser accepts, or `OPTIONS *`) also gets a 404. Next.js never
|
|
43
|
+
* routes these either: it 308s absolute-form targets to their own URL (the
|
|
44
|
+
* `//` after the scheme trips the same check) and 500s `OPTIONS *`. Routing
|
|
45
|
+
* them would let the request line choose the origin of `request.url` that
|
|
46
|
+
* middleware and handlers see, bypassing the Host trust policy. Request-based
|
|
47
|
+
* entries always pass a pathname.
|
|
48
|
+
*
|
|
42
49
|
* @param rawUrl - The raw request target: pathname plus optional `?query`
|
|
43
50
|
*/
|
|
44
51
|
function getRepeatedSlashRedirect(rawUrl) {
|
|
45
|
-
if (!rawUrl.startsWith("/")) return
|
|
52
|
+
if (!rawUrl.startsWith("/")) return { status: 404 };
|
|
46
53
|
const urlParts = rawUrl.split("?");
|
|
47
54
|
const pathname = urlParts[0];
|
|
48
55
|
if (!REPEATED_SLASH_OR_BACKSLASH_RE.test(pathname)) return null;
|
|
@@ -62,7 +69,7 @@ function repeatedSlashRedirectHeaders(location) {
|
|
|
62
69
|
}
|
|
63
70
|
/**
|
|
64
71
|
* Build the Response for a raw request path containing a backslash or a
|
|
65
|
-
* repeated slash. See `getRepeatedSlashRedirect`.
|
|
72
|
+
* repeated slash, or a non-origin-form target. See `getRepeatedSlashRedirect`.
|
|
66
73
|
*/
|
|
67
74
|
function repeatedSlashRedirectResponse(rawUrl) {
|
|
68
75
|
const redirect = getRepeatedSlashRedirect(rawUrl);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import { internalServerErrorResponse } from "./http-error-responses.js";
|
|
2
|
+
import { cloneRequestWithUrl } from "./request-pipeline.js";
|
|
1
3
|
import { getRequestExecutionContext, runWithExecutionContext } from "../shims/request-context.js";
|
|
2
4
|
import "./server-globals.js";
|
|
3
5
|
import { NextRequest } from "../shims/server.js";
|
|
4
|
-
import { internalServerErrorResponse } from "./http-error-responses.js";
|
|
5
|
-
import { cloneRequestWithUrl } from "./request-pipeline.js";
|
|
6
6
|
import { markRouteCacheabilityExplicitResponsePolicy } from "../shims/cacheability-classification.js";
|
|
7
7
|
import { hasCdnResponsePolicy } from "./cache-control.js";
|
|
8
8
|
import { mergeRouteParamsIntoQuery, parseQueryString, urlQueryToSearchParams } from "../utils/query.js";
|
|
@@ -9,6 +9,11 @@
|
|
|
9
9
|
* unit-testable and lives in a normal typed module rather than a codegen
|
|
10
10
|
* template string.
|
|
11
11
|
*/
|
|
12
|
+
/**
|
|
13
|
+
* Fallback for when no build-time `sharedChunks` list is registered. Prefers
|
|
14
|
+
* the chunk-name based list the build writes into the SSR manifest; the file
|
|
15
|
+
* name scan only matches `[name]-[hash]` names, not hash-only ones.
|
|
16
|
+
*/
|
|
12
17
|
export declare function getSharedChunkFiles(manifest: Record<string, string[]>): string[];
|
|
13
18
|
/**
|
|
14
19
|
* Resolve the effective SSR manifest: prefer the caller-supplied object and
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { appendDeploymentIdQuery } from "../utils/deployment-id.js";
|
|
2
2
|
import { createNonceAttribute } from "./html.js";
|
|
3
|
-
import { assetServingUrlFromBaseAnchored } from "../utils/manifest-paths.js";
|
|
3
|
+
import { SSR_MANIFEST_SHARED_CHUNKS_KEY, assetServingUrlFromBaseAnchored } from "../utils/manifest-paths.js";
|
|
4
4
|
import { getPagesClientAssets } from "./pages-client-assets.js";
|
|
5
5
|
//#region src/server/pages-asset-tags.ts
|
|
6
6
|
/**
|
|
@@ -55,7 +55,14 @@ function findModuleKey(manifest, moduleId) {
|
|
|
55
55
|
}
|
|
56
56
|
return matchedKey;
|
|
57
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* Fallback for when no build-time `sharedChunks` list is registered. Prefers
|
|
60
|
+
* the chunk-name based list the build writes into the SSR manifest; the file
|
|
61
|
+
* name scan only matches `[name]-[hash]` names, not hash-only ones.
|
|
62
|
+
*/
|
|
58
63
|
function getSharedChunkFiles(manifest) {
|
|
64
|
+
const recorded = manifest[SSR_MANIFEST_SHARED_CHUNKS_KEY];
|
|
65
|
+
if (recorded) return recorded;
|
|
59
66
|
const cached = sharedChunkFiles.get(manifest);
|
|
60
67
|
if (cached) return cached;
|
|
61
68
|
const files = /* @__PURE__ */ new Set();
|
|
@@ -186,7 +193,7 @@ function collectAssetTags(options) {
|
|
|
186
193
|
const files = getManifestFilesForModule(m, id);
|
|
187
194
|
if (files) for (let fi = 0; fi < files.length; fi++) allFiles.push(files[fi]);
|
|
188
195
|
}
|
|
189
|
-
const sharedFiles =
|
|
196
|
+
const sharedFiles = runtimeAssets.sharedChunks ?? getSharedChunkFiles(m);
|
|
190
197
|
for (const file of sharedFiles) allFiles.push(file);
|
|
191
198
|
} else for (const akey in m) {
|
|
192
199
|
const avals = m[akey];
|
|
@@ -4,7 +4,10 @@ export type PagesClientAssets = {
|
|
|
4
4
|
clientEntry?: string;
|
|
5
5
|
appBootstrapPreinitModules?: string[];
|
|
6
6
|
ssrManifest?: Record<string, string[]>;
|
|
7
|
-
/**
|
|
7
|
+
/**
|
|
8
|
+
* Shared Pages chunk files (framework, vinext runtime, client entry) keyed on
|
|
9
|
+
* chunk names from this client build, in the SSR-manifest key-space.
|
|
10
|
+
*/
|
|
8
11
|
sharedChunks?: string[];
|
|
9
12
|
cssGraph?: Record<string, {
|
|
10
13
|
imports?: string[];
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { MIDDLEWARE_SKIP_HEADER } from "../utils/protocol-headers.js";
|
|
2
2
|
import { addBasePathToPathname, hasBasePath, stripBasePath } from "../utils/base-path.js";
|
|
3
3
|
import { NEXTJS_DEPLOYMENT_ID_HEADER } from "./headers.js";
|
|
4
|
+
import { cloneRequestWithUrl } from "./request-pipeline.js";
|
|
4
5
|
//#region src/server/pages-data-route.ts
|
|
5
6
|
/**
|
|
6
7
|
* Helpers for the Pages Router `/_next/data/{buildId}/{...page}.json` endpoint.
|
|
@@ -191,7 +192,7 @@ function normalizePagesDataRequest(request, buildId, basePath = "", trailingSlas
|
|
|
191
192
|
normalizedUrl.pathname = hadBasePath ? addBasePathToPathname(pagePathname, basePath) : pagePathname;
|
|
192
193
|
return {
|
|
193
194
|
isDataReq: true,
|
|
194
|
-
request:
|
|
195
|
+
request: cloneRequestWithUrl(request, normalizedUrl.href),
|
|
195
196
|
normalizedPathname: pagePathname,
|
|
196
197
|
search: reqUrl.search,
|
|
197
198
|
notFoundResponse: null
|
|
@@ -63,12 +63,30 @@ export declare function detectPathnameLocale(pathname: string, locales: readonly
|
|
|
63
63
|
* `:locale`. After normalisation the request looks like `/en/to-sv` and
|
|
64
64
|
* the rule matches with `:locale=en`.
|
|
65
65
|
*
|
|
66
|
+
* `restoreRootTrailingSlash` makes the root `/en/` rather than `/en`; header
|
|
67
|
+
* callers compute it with `shouldRestoreLocaleRootTrailingSlash`. Redirect
|
|
68
|
+
* and rewrite callers do not pass it yet.
|
|
69
|
+
*
|
|
66
70
|
* Ported from Next.js: packages/next/src/server/lib/router-utils/resolve-routes.ts
|
|
67
71
|
* https://github.com/vercel/next.js/blob/canary/packages/next/src/server/lib/router-utils/resolve-routes.ts
|
|
68
72
|
*/
|
|
69
73
|
export declare function normalizeDefaultLocalePathname(pathname: string, i18n: NextI18nConfig | null | undefined, options?: {
|
|
70
74
|
hostname?: string | null;
|
|
75
|
+
restoreRootTrailingSlash?: boolean;
|
|
71
76
|
}): string;
|
|
77
|
+
/**
|
|
78
|
+
* Whether Next.js re-adds the root's trailing slash after splicing in the
|
|
79
|
+
* default locale: the raw request pathname (basePath included, so `/docs`
|
|
80
|
+
* stays `/docs/en` while `/docs/` becomes `/docs/en/`) ends with `/`, and
|
|
81
|
+
* `trailingSlash` is on without `skipProxyUrlNormalize`.
|
|
82
|
+
*
|
|
83
|
+
* Ported from Next.js: packages/next/src/server/lib/router-utils/resolve-routes.ts
|
|
84
|
+
* (`hadTrailingSlash` + `maybeAddTrailingSlash`).
|
|
85
|
+
*/
|
|
86
|
+
export declare function shouldRestoreLocaleRootTrailingSlash(rawPathname: string, config: {
|
|
87
|
+
trailingSlash?: boolean;
|
|
88
|
+
skipProxyUrlNormalize?: boolean;
|
|
89
|
+
}): boolean;
|
|
72
90
|
/**
|
|
73
91
|
* Extract locale prefix from a URL path.
|
|
74
92
|
* e.g. /fr/about -> { locale: "fr", url: "/about", hadPrefix: true }
|
|
@@ -51,6 +51,10 @@ function detectPathnameLocale(pathname, locales) {
|
|
|
51
51
|
* `:locale`. After normalisation the request looks like `/en/to-sv` and
|
|
52
52
|
* the rule matches with `:locale=en`.
|
|
53
53
|
*
|
|
54
|
+
* `restoreRootTrailingSlash` makes the root `/en/` rather than `/en`; header
|
|
55
|
+
* callers compute it with `shouldRestoreLocaleRootTrailingSlash`. Redirect
|
|
56
|
+
* and rewrite callers do not pass it yet.
|
|
57
|
+
*
|
|
54
58
|
* Ported from Next.js: packages/next/src/server/lib/router-utils/resolve-routes.ts
|
|
55
59
|
* https://github.com/vercel/next.js/blob/canary/packages/next/src/server/lib/router-utils/resolve-routes.ts
|
|
56
60
|
*/
|
|
@@ -59,10 +63,22 @@ function normalizeDefaultLocalePathname(pathname, i18n, options = {}) {
|
|
|
59
63
|
if (pathname.startsWith("/_next/") || pathname.startsWith("/__vinext/")) return pathname;
|
|
60
64
|
if (detectPathnameLocale(pathname, i18n.locales)) return pathname;
|
|
61
65
|
const defaultLocale = detectDomainLocale(i18n.domains, options.hostname ?? void 0)?.defaultLocale ?? i18n.defaultLocale;
|
|
62
|
-
if (pathname === "/") return `/${defaultLocale}`;
|
|
66
|
+
if (pathname === "/") return options.restoreRootTrailingSlash ? `/${defaultLocale}/` : `/${defaultLocale}`;
|
|
63
67
|
return `/${defaultLocale}${pathname}`;
|
|
64
68
|
}
|
|
65
69
|
/**
|
|
70
|
+
* Whether Next.js re-adds the root's trailing slash after splicing in the
|
|
71
|
+
* default locale: the raw request pathname (basePath included, so `/docs`
|
|
72
|
+
* stays `/docs/en` while `/docs/` becomes `/docs/en/`) ends with `/`, and
|
|
73
|
+
* `trailingSlash` is on without `skipProxyUrlNormalize`.
|
|
74
|
+
*
|
|
75
|
+
* Ported from Next.js: packages/next/src/server/lib/router-utils/resolve-routes.ts
|
|
76
|
+
* (`hadTrailingSlash` + `maybeAddTrailingSlash`).
|
|
77
|
+
*/
|
|
78
|
+
function shouldRestoreLocaleRootTrailingSlash(rawPathname, config) {
|
|
79
|
+
return Boolean(config.trailingSlash && !config.skipProxyUrlNormalize && rawPathname.endsWith("/"));
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
66
82
|
* Extract locale prefix from a URL path.
|
|
67
83
|
* e.g. /fr/about -> { locale: "fr", url: "/about", hadPrefix: true }
|
|
68
84
|
* /about -> { locale: defaultLocale, url: "/about", hadPrefix: false }
|
|
@@ -243,4 +259,4 @@ function resolvePagesI18nRequest(url, i18nConfig, headers, hostname, basePath =
|
|
|
243
259
|
};
|
|
244
260
|
}
|
|
245
261
|
//#endregion
|
|
246
|
-
export { detectDomainLocale, detectLocaleFromAcceptLanguage, detectPathnameLocale, extractLocaleFromUrl, getLocaleRedirect, normalizeDefaultLocalePathname, parseCookieLocaleFromHeader, resolvePagesI18nRequest, stripI18nLocaleForApiRoute };
|
|
262
|
+
export { detectDomainLocale, detectLocaleFromAcceptLanguage, detectPathnameLocale, extractLocaleFromUrl, getLocaleRedirect, normalizeDefaultLocalePathname, parseCookieLocaleFromHeader, resolvePagesI18nRequest, shouldRestoreLocaleRootTrailingSlash, stripI18nLocaleForApiRoute };
|
|
@@ -15,15 +15,17 @@ export type PagesReqResRequest = Readable & {
|
|
|
15
15
|
draftMode?: true;
|
|
16
16
|
previewData: PagesPreviewData | false;
|
|
17
17
|
};
|
|
18
|
+
type PagesReqResHeaderValue = string | number | boolean | string[];
|
|
18
19
|
type PagesReqResHeaders = {
|
|
19
|
-
[key: string]:
|
|
20
|
+
[key: string]: PagesReqResHeaderValue;
|
|
20
21
|
};
|
|
21
22
|
export type PagesReqResResponse = Writable & {
|
|
22
23
|
statusCode: number;
|
|
23
24
|
readonly headersSent: boolean;
|
|
24
25
|
writeHead: (code: number, headers?: PagesReqResHeaders) => PagesReqResResponse;
|
|
25
|
-
setHeader: (name: string, value:
|
|
26
|
-
|
|
26
|
+
setHeader: (name: string, value: PagesReqResHeaderValue) => PagesReqResResponse;
|
|
27
|
+
appendHeader: (name: string, value: string | readonly string[]) => PagesReqResResponse;
|
|
28
|
+
getHeader: (name: string) => PagesReqResHeaderValue | undefined;
|
|
27
29
|
status: (code: number) => PagesReqResResponse;
|
|
28
30
|
json: (data: unknown) => void;
|
|
29
31
|
send: (data: unknown) => void;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { parseCookieHeader } from "../utils/parse-cookie.js";
|
|
2
|
+
import { getRequestExecutionContext } from "../shims/request-context.js";
|
|
2
3
|
import { readStreamAsTextWithLimit } from "../utils/text-stream.js";
|
|
3
4
|
import { DEFAULT_PAGES_API_BODY_SIZE_LIMIT } from "./pages-body-parser-config.js";
|
|
4
5
|
import { PagesBodyParseError, getMediaType, isJsonMediaType } from "./pages-media-type.js";
|
|
@@ -13,6 +14,18 @@ const NO_BODY_RESPONSE_STATUSES = /* @__PURE__ */ new Set([
|
|
|
13
14
|
205,
|
|
14
15
|
304
|
|
15
16
|
]);
|
|
17
|
+
const HTTP_TOKEN_PATTERN = /^[\^_`a-zA-Z\-0-9!#$%&'*+.|~]+$/;
|
|
18
|
+
const INVALID_HEADER_VALUE_CHAR_PATTERN = /[^\t\x20-\x7e\x80-\xff]/;
|
|
19
|
+
function createNodeTypeError(code, message) {
|
|
20
|
+
return Object.assign(new TypeError(message), { code });
|
|
21
|
+
}
|
|
22
|
+
function validateAppendedHeader(name, value) {
|
|
23
|
+
if (typeof name !== "string" || !name || !HTTP_TOKEN_PATTERN.test(name)) throw createNodeTypeError("ERR_INVALID_HTTP_TOKEN", `Header name must be a valid HTTP token ["${String(name)}"]`);
|
|
24
|
+
for (const item of Array.isArray(value) ? value : [value]) {
|
|
25
|
+
if (item === void 0) throw createNodeTypeError("ERR_HTTP_INVALID_HEADER_VALUE", `Invalid value "undefined" for header "${name}"`);
|
|
26
|
+
if (INVALID_HEADER_VALUE_CHAR_PATTERN.test(String(item))) throw createNodeTypeError("ERR_INVALID_CHAR", `Invalid character in header content ["${name}"]`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
16
29
|
async function readPagesRequestBodyWithLimit(request, maxBytes) {
|
|
17
30
|
if (!request.body) return "";
|
|
18
31
|
return readStreamAsTextWithLimit(request.body, maxBytes, () => {
|
|
@@ -120,9 +133,9 @@ var PagesResponseStream = class extends Writable {
|
|
|
120
133
|
resolveResponse;
|
|
121
134
|
rejectResponse;
|
|
122
135
|
resStatusCode = 200;
|
|
123
|
-
resHeaders =
|
|
124
|
-
setCookieHeaders = [];
|
|
136
|
+
resHeaders = Object.create(null);
|
|
125
137
|
resolved = false;
|
|
138
|
+
headWritten = false;
|
|
126
139
|
controller = null;
|
|
127
140
|
bufferedChunks = [];
|
|
128
141
|
streamEnded = false;
|
|
@@ -150,15 +163,21 @@ var PagesResponseStream = class extends Writable {
|
|
|
150
163
|
}
|
|
151
164
|
writeHead(code, headers) {
|
|
152
165
|
this.resStatusCode = code;
|
|
153
|
-
if (headers) for (const [key, value] of Object.entries(headers)) this.setHeaderValue(key, value, {
|
|
166
|
+
if (headers) for (const [key, value] of Object.entries(headers)) this.setHeaderValue(key, value, { append: false });
|
|
167
|
+
this.headWritten = true;
|
|
154
168
|
return this;
|
|
155
169
|
}
|
|
156
170
|
setHeader(name, value) {
|
|
157
|
-
this.setHeaderValue(name, value, {
|
|
171
|
+
this.setHeaderValue(name, value, { append: false });
|
|
172
|
+
return this;
|
|
173
|
+
}
|
|
174
|
+
appendHeader(name, value) {
|
|
175
|
+
if (this.headWritten || this.headersSent) throw Object.assign(/* @__PURE__ */ new Error("Cannot append headers after they are sent to the client"), { code: "ERR_HTTP_HEADERS_SENT" });
|
|
176
|
+
validateAppendedHeader(name, value);
|
|
177
|
+
this.setHeaderValue(name, value, { append: true });
|
|
158
178
|
return this;
|
|
159
179
|
}
|
|
160
180
|
getHeader(name) {
|
|
161
|
-
if (name.toLowerCase() === "set-cookie") return this.setCookieHeaders.length > 0 ? this.setCookieHeaders : void 0;
|
|
162
181
|
return this.resHeaders[name.toLowerCase()];
|
|
163
182
|
}
|
|
164
183
|
status(code) {
|
|
@@ -196,9 +215,7 @@ var PagesResponseStream = class extends Writable {
|
|
|
196
215
|
return this;
|
|
197
216
|
}
|
|
198
217
|
getHeaders() {
|
|
199
|
-
|
|
200
|
-
if (this.setCookieHeaders.length > 0) headers["set-cookie"] = this.setCookieHeaders;
|
|
201
|
-
return headers;
|
|
218
|
+
return { ...this.resHeaders };
|
|
202
219
|
}
|
|
203
220
|
setPreviewData(data, options = {}) {
|
|
204
221
|
setPagesPreviewData(this, data, options);
|
|
@@ -250,13 +267,15 @@ var PagesResponseStream = class extends Writable {
|
|
|
250
267
|
callback(error);
|
|
251
268
|
}
|
|
252
269
|
setHeaderValue(name, value, options) {
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
this.
|
|
270
|
+
const key = name.toLowerCase();
|
|
271
|
+
const existing = this.resHeaders[key];
|
|
272
|
+
if (!options.append || existing === void 0) {
|
|
273
|
+
this.resHeaders[key] = value;
|
|
257
274
|
return;
|
|
258
275
|
}
|
|
259
|
-
|
|
276
|
+
const values = Array.isArray(existing) ? existing : [existing];
|
|
277
|
+
values.push(...Array.isArray(value) ? value : [value]);
|
|
278
|
+
this.resHeaders[key] = values;
|
|
260
279
|
}
|
|
261
280
|
releasePendingWrite(error) {
|
|
262
281
|
const callback = this.pendingWrite;
|
|
@@ -267,8 +286,8 @@ var PagesResponseStream = class extends Writable {
|
|
|
267
286
|
if (this.resolved) return;
|
|
268
287
|
this.resolved = true;
|
|
269
288
|
const headers = new Headers();
|
|
270
|
-
for (const [key, value] of Object.entries(this.resHeaders)) headers.
|
|
271
|
-
|
|
289
|
+
for (const [key, value] of Object.entries(this.resHeaders)) if (Array.isArray(value)) for (const item of value) headers.append(key, String(item));
|
|
290
|
+
else headers.set(key, String(value));
|
|
272
291
|
if (NO_BODY_RESPONSE_STATUSES.has(this.resStatusCode)) {
|
|
273
292
|
this.discardBody = true;
|
|
274
293
|
this.bufferedChunks.length = 0;
|
|
@@ -359,10 +378,10 @@ function createPagesReqRes(options) {
|
|
|
359
378
|
*/
|
|
360
379
|
function createPagesApiReqRes(options) {
|
|
361
380
|
const { req, res, responsePromise } = createPagesReqRes(options);
|
|
362
|
-
const trustedRevalidateOrigin = options.trustedRevalidateOrigin ?? new URL(options.request.url).origin;
|
|
363
381
|
return {
|
|
364
382
|
req,
|
|
365
383
|
res: Object.assign(res, { async revalidate(urlPath, opts) {
|
|
384
|
+
const trustedRevalidateOrigin = options.trustedRevalidateOrigin ?? (getRequestExecutionContext()?.dispatchPagesRevalidate ? new URL(options.request.url).origin : void 0);
|
|
366
385
|
await performOnDemandRevalidate(options.request.headers, urlPath, opts, trustedRevalidateOrigin, options.allowedRevalidateHeaderKeys);
|
|
367
386
|
} }),
|
|
368
387
|
responsePromise
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { isUnknownRecord } from "../utils/record.js";
|
|
2
2
|
import { isBotUserAgent } from "../utils/html-limited-bots.js";
|
|
3
|
-
import { normalizePathnameForRouteMatch } from "../routing/utils.js";
|
|
4
3
|
import { NEXTJS_CACHE_HEADER, NEXTJS_DEPLOYMENT_ID_HEADER } from "./headers.js";
|
|
4
|
+
import { normalizePathnameForRouteMatch } from "../routing/utils.js";
|
|
5
5
|
import { isDangerousScheme } from "../shims/url-safety.js";
|
|
6
6
|
import { extractLocaleFromUrl } from "./pages-i18n.js";
|
|
7
7
|
import { buildNextDataPropsJsonResponse } from "./pages-data-route.js";
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { preserveFullyBufferedBodyMetadata } from "./fully-buffered-response.js";
|
|
2
2
|
import { closeAfterResponse, closeAfterResponseWithBody, createRequestContext, runWithRequestContext } from "../shims/unified-request-context.js";
|
|
3
3
|
import { PRERENDER_REVALIDATE_HEADER } from "../utils/protocol-headers.js";
|
|
4
|
+
import { NEXTJS_CACHE_HEADER, NEXTJS_DEPLOYMENT_ID_HEADER, VINEXT_CACHE_HEADER, VINEXT_REVALIDATED_CACHE_TAG_HEADER } from "./headers.js";
|
|
4
5
|
import { normalizePathnameForRouteMatch } from "../routing/utils.js";
|
|
5
6
|
import { patternToNextFormat } from "../routing/route-validation.js";
|
|
6
7
|
import { getRequestExecutionContext } from "../shims/request-context.js";
|
|
7
|
-
import { NEXTJS_CACHE_HEADER, NEXTJS_DEPLOYMENT_ID_HEADER, VINEXT_CACHE_HEADER, VINEXT_REVALIDATED_CACHE_TAG_HEADER } from "./headers.js";
|
|
8
8
|
import { extractLocaleFromUrl, resolvePagesI18nRequest } from "./pages-i18n.js";
|
|
9
9
|
import { buildNextDataNotFoundResponse, buildNextDataPropsJsonResponse, normalizePagesDataRequest, parseNextDataPathname } from "./pages-data-route.js";
|
|
10
10
|
import { reportRequestError } from "./instrumentation.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { isBotUserAgent } from "../utils/html-limited-bots.js";
|
|
2
|
-
import { getRequestExecutionContext } from "../shims/request-context.js";
|
|
3
2
|
import { NEXTJS_CACHE_HEADER, VINEXT_REVALIDATED_CACHE_TAG_HEADER } from "./headers.js";
|
|
3
|
+
import { getRequestExecutionContext } from "../shims/request-context.js";
|
|
4
4
|
import { reportRequestError } from "./instrumentation.js";
|
|
5
5
|
import { getCdnCacheAdapter } from "../shims/cdn-cache.js";
|
|
6
6
|
import { markRouteCacheabilityExplicitResponsePolicy } from "../shims/cacheability-classification.js";
|
|
@@ -15,7 +15,7 @@ type PageRouteMatch = {
|
|
|
15
15
|
dataKind?: PagesRouteDataKind;
|
|
16
16
|
};
|
|
17
17
|
};
|
|
18
|
-
export declare function fetchWorkerFilesystemRoute(request: Request, requestPathname: string, phase: FilesystemRoutePhase, fetchAsset: (request: Request) => Promise<Response>, publicFiles: ReadonlySet<string>, basePath?: string, assetPathPrefix?: string,
|
|
18
|
+
export declare function fetchWorkerFilesystemRoute(request: Request, requestPathname: string, phase: FilesystemRoutePhase, fetchAsset: (request: Request) => Promise<Response>, publicFiles: ReadonlySet<string>, basePath?: string, assetPathPrefix?: string, pathnameHasBasePath?: boolean): Promise<Response | false>;
|
|
19
19
|
export type MiddlewareResult = {
|
|
20
20
|
continue: boolean;
|
|
21
21
|
/** The pathname matches middleware, irrespective of request `has`/`missing` conditions. */
|
|
@@ -54,6 +54,11 @@ export type PagesPipelineDeps = {
|
|
|
54
54
|
recordCacheability?: boolean;
|
|
55
55
|
rawSearch?: string;
|
|
56
56
|
configMatchPathname?: string;
|
|
57
|
+
/**
|
|
58
|
+
* `shouldRestoreLocaleRootTrailingSlash` for the raw request pathname
|
|
59
|
+
* (basePath included), which the basePath-stripped request no longer shows.
|
|
60
|
+
*/
|
|
61
|
+
restoreLocaleRootTrailingSlash?: boolean;
|
|
57
62
|
/**
|
|
58
63
|
* Validate an on-demand revalidation credential using the runtime's
|
|
59
64
|
* authoritative build secret. Production adapters must inject the verifier
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
import { PRERENDER_REVALIDATE_HEADER } from "../utils/protocol-headers.js";
|
|
2
2
|
import { requestContextFromRequest } from "../config/request-context.js";
|
|
3
3
|
import { isExternalUrl } from "../utils/external-url.js";
|
|
4
|
-
import { applyMiddlewareRequestHeaders, matchRedirect, matchRewrite, preserveRedirectDestinationQuery, proxyExternalRequest, sanitizeDestination } from "../config/config-matchers.js";
|
|
5
|
-
import { assetPrefixPathname, isNextStaticPath } from "../utils/asset-prefix.js";
|
|
6
|
-
import { normalizePathnameForRouteMatchStrict } from "../routing/utils.js";
|
|
7
4
|
import { addBasePathToPathname, hasBasePath } from "../utils/base-path.js";
|
|
8
|
-
import { patternToNextFormat } from "../routing/route-validation.js";
|
|
9
5
|
import { VINEXT_PRERENDER_REWRITTEN_HEADER } from "./headers.js";
|
|
10
6
|
import { methodNotAllowedResponse, notFoundStaticAssetResponse, sanitizeMethodNotAllowedHeaders } from "./http-error-responses.js";
|
|
11
7
|
import { cloneRequestWithUrl, normalizeTrailingSlash } from "./request-pipeline.js";
|
|
8
|
+
import { applyMiddlewareRequestHeaders, matchRedirect, matchRewrite, preserveRedirectDestinationQuery, proxyExternalRequest, sanitizeDestination } from "../config/config-matchers.js";
|
|
9
|
+
import { assetPrefixPathname, isAssetPrefixBuildAsset, isNextStaticPath } from "../utils/asset-prefix.js";
|
|
10
|
+
import { normalizePathnameForRouteMatchStrict } from "../routing/utils.js";
|
|
11
|
+
import { patternToNextFormat } from "../routing/route-validation.js";
|
|
12
12
|
import { detectPathnameLocale, normalizeDefaultLocalePathname, stripI18nLocaleForApiRoute } from "./pages-i18n.js";
|
|
13
13
|
import { buildMiddlewarePrefetchSkipResponse } from "./pages-data-route.js";
|
|
14
14
|
import { markRouteCacheabilityDynamic } from "../shims/cacheability-classification.js";
|
|
15
15
|
import { isOnDemandRevalidateRequest } from "./revalidation-request.js";
|
|
16
16
|
import { mergeRewriteQuery } from "../utils/query.js";
|
|
17
|
+
import { withExternalRewriteResponseHeaders } from "./middleware-response-headers.js";
|
|
17
18
|
import { setFrameworkRequestRoute } from "./request-tracing.js";
|
|
18
19
|
import { applyConfigHeadersToHeaderRecord } from "./config-headers.js";
|
|
19
20
|
import { finalizeMissingStaticAssetResponse, mergeHeaders } from "./worker-utils.js";
|
|
@@ -33,7 +34,7 @@ function headersFromRecord(record) {
|
|
|
33
34
|
else headers.set(name, value);
|
|
34
35
|
return headers;
|
|
35
36
|
}
|
|
36
|
-
async function fetchWorkerFilesystemRoute(request, requestPathname, phase, fetchAsset, publicFiles, basePath = "", assetPathPrefix = "",
|
|
37
|
+
async function fetchWorkerFilesystemRoute(request, requestPathname, phase, fetchAsset, publicFiles, basePath = "", assetPathPrefix = "", pathnameHasBasePath = true) {
|
|
37
38
|
const isRetrievalMethod = request.method === "GET" || request.method === "HEAD";
|
|
38
39
|
const assetUrl = new URL(request.url);
|
|
39
40
|
assetUrl.pathname = requestPathname;
|
|
@@ -46,7 +47,8 @@ async function fetchWorkerFilesystemRoute(request, requestPathname, phase, fetch
|
|
|
46
47
|
} catch {
|
|
47
48
|
return false;
|
|
48
49
|
}
|
|
49
|
-
|
|
50
|
+
if (!pathnameHasBasePath && !isAssetPrefixBuildAsset(decodedAssetUrl.pathname, assetPathPrefix)) return false;
|
|
51
|
+
const isPublicFile = pathnameHasBasePath && publicFiles.has(publicFileKey);
|
|
50
52
|
if (!isPublicFile && (requestPathname === "/api" || requestPathname.startsWith("/api/"))) return false;
|
|
51
53
|
if (phase === "direct" && isRetrievalMethod && !isPublicFile) return false;
|
|
52
54
|
if (!isPublicFile && !isNextStaticPath(decodedAssetUrl.pathname, basePath, assetPathPrefix)) return false;
|
|
@@ -79,7 +81,7 @@ function wrapMiddlewareWithBasePath(runMiddleware, basePath, hadBasePath) {
|
|
|
79
81
|
return (request, ctx, opts) => {
|
|
80
82
|
const mwUrl = new URL(request.url);
|
|
81
83
|
mwUrl.pathname = addBasePathToPathname(mwUrl.pathname, basePath);
|
|
82
|
-
return runMiddleware(
|
|
84
|
+
return runMiddleware(cloneRequestWithUrl(request, mwUrl.toString()), ctx, opts);
|
|
83
85
|
};
|
|
84
86
|
}
|
|
85
87
|
/**
|
|
@@ -118,6 +120,10 @@ async function runPagesRequest(request, deps) {
|
|
|
118
120
|
const reqCtx = requestContextFromRequest(request);
|
|
119
121
|
const requestHostname = i18nConfig ? url.hostname : "";
|
|
120
122
|
const requestConfigMatchPathname = i18nConfig ? normalizeDefaultLocalePathname(requestConfigPathname, i18nConfig, { hostname: requestHostname }) : requestConfigPathname;
|
|
123
|
+
const requestHeaderMatchPathname = i18nConfig ? normalizeDefaultLocalePathname(requestConfigPathname, i18nConfig, {
|
|
124
|
+
hostname: requestHostname,
|
|
125
|
+
restoreRootTrailingSlash: deps.restoreLocaleRootTrailingSlash
|
|
126
|
+
}) : requestConfigPathname;
|
|
121
127
|
if (configRedirects.length) {
|
|
122
128
|
const redirect = matchRedirect(requestConfigMatchPathname, configRedirects, reqCtx, basePathState, conditionalRedirectCacheability);
|
|
123
129
|
if (redirect) {
|
|
@@ -141,14 +147,16 @@ async function runPagesRequest(request, deps) {
|
|
|
141
147
|
hadBasePath: resolvedPathnameHasBasePath
|
|
142
148
|
});
|
|
143
149
|
const middlewareHeaders = {};
|
|
150
|
+
let middlewareCookies = [];
|
|
144
151
|
const mergeConfigHeadersIntoEarlyResponse = (response) => {
|
|
145
152
|
if (configHeaders.length === 0) return response;
|
|
146
153
|
const matchedConfigHeaders = {};
|
|
147
154
|
applyConfigHeadersToHeaderRecord(matchedConfigHeaders, {
|
|
148
155
|
configHeaders,
|
|
149
|
-
pathname:
|
|
156
|
+
pathname: requestHeaderMatchPathname,
|
|
150
157
|
requestContext: reqCtx,
|
|
151
158
|
basePathState,
|
|
159
|
+
middlewareHeaders: response.headers,
|
|
152
160
|
recordCacheability: deps.recordCacheability
|
|
153
161
|
});
|
|
154
162
|
return mergeHeaders(response, matchedConfigHeaders);
|
|
@@ -210,6 +218,8 @@ async function runPagesRequest(request, deps) {
|
|
|
210
218
|
else if (existing) middlewareHeaders[key] = [existing, value];
|
|
211
219
|
else middlewareHeaders[key] = [value];
|
|
212
220
|
} else middlewareHeaders[key] = value;
|
|
221
|
+
const stagedCookies = middlewareHeaders["set-cookie"];
|
|
222
|
+
if (Array.isArray(stagedCookies)) middlewareCookies = [...stagedCookies];
|
|
213
223
|
if (result.rewriteUrl) {
|
|
214
224
|
resolvedUrl = result.rewriteUrl;
|
|
215
225
|
resolvedPathnameIsRequestPathname = false;
|
|
@@ -249,26 +259,24 @@ async function runPagesRequest(request, deps) {
|
|
|
249
259
|
};
|
|
250
260
|
if (configHeaders.length) applyConfigHeadersToHeaderRecord(middlewareHeaders, {
|
|
251
261
|
configHeaders,
|
|
252
|
-
pathname:
|
|
262
|
+
pathname: requestHeaderMatchPathname,
|
|
253
263
|
requestContext: reqCtx,
|
|
254
264
|
basePathState,
|
|
255
265
|
recordCacheability: deps.recordCacheability
|
|
256
266
|
});
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
267
|
+
const proxyConfigRewrite = async (destination) => ({
|
|
268
|
+
type: "response",
|
|
269
|
+
response: withExternalRewriteResponseHeaders(await proxyExternal(request, destination), new Headers(), middlewareCookies)
|
|
270
|
+
});
|
|
271
|
+
if (isExternalUrl(resolvedUrl)) return {
|
|
272
|
+
type: "response",
|
|
273
|
+
response: withExternalRewriteResponseHeaders(await proxyExternal(request, resolvedUrl), headersFromRecord(middlewareHeaders), middlewareCookies)
|
|
274
|
+
};
|
|
264
275
|
let configRewriteFired = false;
|
|
265
276
|
for (const rewrite of configRewrites.beforeFiles ?? []) {
|
|
266
277
|
const rewritten = matchRewrite(configSourcePathname(), [rewrite], rewriteRequestContext(), currentBasePathState(), configSourcePathname(), conditionalRewriteCacheability);
|
|
267
278
|
if (rewritten) {
|
|
268
|
-
if (isExternalUrl(rewritten)) return
|
|
269
|
-
type: "response",
|
|
270
|
-
response: await proxyExternal(request, rewritten)
|
|
271
|
-
};
|
|
279
|
+
if (isExternalUrl(rewritten)) return proxyConfigRewrite(rewritten);
|
|
272
280
|
resolvedUrl = mergeRewriteQuery(resolvedUrl, rewritten);
|
|
273
281
|
resolvedPathname = pathnameForResolvedUrl(resolvedUrl);
|
|
274
282
|
resolvedPathnameIsRequestPathname = false;
|
|
@@ -279,13 +287,13 @@ async function runPagesRequest(request, deps) {
|
|
|
279
287
|
const initialFilesystemResult = await serveFilesystemRoute(resolvedPathname, resolvedPathnameIsRequestPathname ? "direct" : "beforeFiles");
|
|
280
288
|
if (initialFilesystemResult) return initialFilesystemResult;
|
|
281
289
|
const isMissingBuildAsset = () => isNextStaticPath(resolvedPathname, "", assetPrefixPathname(deps.assetPrefix ?? ""));
|
|
282
|
-
const isOutsideBasePathUnclaimed = () => basePath && !
|
|
290
|
+
const isOutsideBasePathUnclaimed = () => basePath && !resolvedPathnameHasBasePath;
|
|
283
291
|
const outOfBasePathNotFound = () => ({
|
|
284
292
|
type: "response",
|
|
285
|
-
response: isMissingBuildAsset() ? notFoundStaticAssetResponse(headersFromRecord(middlewareHeaders)) : new Response("This page could not be found", {
|
|
293
|
+
response: isMissingBuildAsset() ? notFoundStaticAssetResponse(headersFromRecord(middlewareHeaders)) : mergeHeaders(new Response("This page could not be found", {
|
|
286
294
|
status: 404,
|
|
287
295
|
headers: { "Content-Type": "text/html; charset=utf-8" }
|
|
288
|
-
})
|
|
296
|
+
}), middlewareHeaders)
|
|
289
297
|
});
|
|
290
298
|
const handleResolvedApiRoute = async () => {
|
|
291
299
|
if (isOutsideBasePathUnclaimed()) return null;
|
|
@@ -327,10 +335,7 @@ async function runPagesRequest(request, deps) {
|
|
|
327
335
|
if (!pageMatch || pageMatch.route.isDynamic) for (const rewrite of configRewrites.afterFiles ?? []) {
|
|
328
336
|
const rewritten = matchRewrite(configSourcePathname(), [rewrite], rewriteRequestContext(), currentBasePathState(), configSourcePathname(), conditionalRewriteCacheability);
|
|
329
337
|
if (rewritten) {
|
|
330
|
-
if (isExternalUrl(rewritten)) return
|
|
331
|
-
type: "response",
|
|
332
|
-
response: await proxyExternal(request, rewritten)
|
|
333
|
-
};
|
|
338
|
+
if (isExternalUrl(rewritten)) return proxyConfigRewrite(rewritten);
|
|
334
339
|
resolvedUrl = mergeRewriteQuery(resolvedUrl, rewritten);
|
|
335
340
|
resolvedPathname = pathnameForResolvedUrl(resolvedUrl);
|
|
336
341
|
resolvedPathnameIsRequestPathname = false;
|
|
@@ -355,10 +360,7 @@ async function runPagesRequest(request, deps) {
|
|
|
355
360
|
if ((isOutsideBasePathUnclaimed() || isDataReq || isDataRequest) && !renderPageMatch && configRewrites.fallback?.length) for (const rewrite of configRewrites.fallback) {
|
|
356
361
|
const fallbackRewrite = matchRewrite(configSourcePathname(), [rewrite], rewriteRequestContext(), currentBasePathState(), configSourcePathname(), conditionalRewriteCacheability);
|
|
357
362
|
if (!fallbackRewrite) continue;
|
|
358
|
-
if (isExternalUrl(fallbackRewrite)) return
|
|
359
|
-
type: "response",
|
|
360
|
-
response: await proxyExternal(request, fallbackRewrite)
|
|
361
|
-
};
|
|
363
|
+
if (isExternalUrl(fallbackRewrite)) return proxyConfigRewrite(fallbackRewrite);
|
|
362
364
|
resolvedUrl = mergeRewriteQuery(resolvedUrl, fallbackRewrite);
|
|
363
365
|
resolvedPathname = pathnameForResolvedUrl(resolvedUrl);
|
|
364
366
|
resolvedPathnameIsRequestPathname = false;
|
|
@@ -384,10 +386,7 @@ async function runPagesRequest(request, deps) {
|
|
|
384
386
|
if (response.status === 404 && shouldDeferErrorPageOnMiss && configRewrites.fallback?.length) for (const rewrite of configRewrites.fallback) {
|
|
385
387
|
const fallbackRewrite = matchRewrite(configSourcePathname(), [rewrite], rewriteRequestContext(), currentBasePathState(), configSourcePathname(), conditionalRewriteCacheability);
|
|
386
388
|
if (!fallbackRewrite) continue;
|
|
387
|
-
if (isExternalUrl(fallbackRewrite)) return
|
|
388
|
-
type: "response",
|
|
389
|
-
response: await proxyExternal(request, fallbackRewrite)
|
|
390
|
-
};
|
|
389
|
+
if (isExternalUrl(fallbackRewrite)) return proxyConfigRewrite(fallbackRewrite);
|
|
391
390
|
resolvedUrl = mergeRewriteQuery(resolvedUrl, fallbackRewrite);
|
|
392
391
|
resolvedPathname = pathnameForResolvedUrl(resolvedUrl);
|
|
393
392
|
resolvedPathnameIsRequestPathname = false;
|
|
@@ -437,10 +436,7 @@ async function runPagesRequest(request, deps) {
|
|
|
437
436
|
if (!devPageMatch && configRewrites.fallback?.length) for (const rewrite of configRewrites.fallback) {
|
|
438
437
|
const fallbackRewrite = matchRewrite(configSourcePathname(), [rewrite], rewriteRequestContext(), currentBasePathState(), configSourcePathname(), conditionalRewriteCacheability);
|
|
439
438
|
if (!fallbackRewrite) continue;
|
|
440
|
-
if (isExternalUrl(fallbackRewrite)) return
|
|
441
|
-
type: "response",
|
|
442
|
-
response: await proxyExternal(request, fallbackRewrite)
|
|
443
|
-
};
|
|
439
|
+
if (isExternalUrl(fallbackRewrite)) return proxyConfigRewrite(fallbackRewrite);
|
|
444
440
|
resolvedUrl = mergeRewriteQuery(resolvedUrl, fallbackRewrite);
|
|
445
441
|
resolvedPathname = pathnameForResolvedUrl(resolvedUrl);
|
|
446
442
|
resolvedPathnameIsRequestPathname = false;
|