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.
Files changed (283) hide show
  1. package/README.md +13 -10
  2. package/dist/build/client-build-config.d.ts +64 -3
  3. package/dist/build/client-build-config.js +131 -4
  4. package/dist/build/client-reference-groups.d.ts +163 -0
  5. package/dist/build/client-reference-groups.js +534 -0
  6. package/dist/build/module-dependency-cache.d.ts +31 -0
  7. package/dist/build/module-dependency-cache.js +51 -1
  8. package/dist/build/next-client-runtime-manifests.d.ts +10 -1
  9. package/dist/build/next-client-runtime-manifests.js +19 -4
  10. package/dist/build/nitro-public-files.d.ts +24 -0
  11. package/dist/build/nitro-public-files.js +60 -0
  12. package/dist/build/output-root-externals.d.ts +21 -0
  13. package/dist/build/output-root-externals.js +40 -0
  14. package/dist/build/pages-client-assets-module.js +1 -1
  15. package/dist/build/prerender-paths.js +6 -3
  16. package/dist/build/prerender.js +1 -1
  17. package/dist/build/server-actions-encryption-key.d.ts +23 -0
  18. package/dist/build/server-actions-encryption-key.js +101 -0
  19. package/dist/build/ssr-manifest.d.ts +3 -0
  20. package/dist/build/ssr-manifest.js +10 -1
  21. package/dist/check.js +5 -6
  22. package/dist/cli-dev-config.js +3 -3
  23. package/dist/cli.js +1 -1
  24. package/dist/client/client-rewrite-params.d.ts +9 -0
  25. package/dist/client/client-rewrite-params.js +20 -0
  26. package/dist/client/dev-error-overlay.js +2 -1
  27. package/dist/client/navigation-runtime.d.ts +25 -2
  28. package/dist/client/navigation-runtime.js +42 -11
  29. package/dist/client/vinext-next-data.d.ts +0 -1
  30. package/dist/config/config-matchers.d.ts +15 -40
  31. package/dist/config/config-matchers.js +195 -262
  32. package/dist/config/config-source.d.ts +34 -0
  33. package/dist/config/config-source.js +141 -0
  34. package/dist/config/header-params.d.ts +29 -0
  35. package/dist/config/header-params.js +106 -0
  36. package/dist/config/next-config.d.ts +7 -5
  37. package/dist/config/next-config.js +120 -7
  38. package/dist/entries/app-browser-entry.d.ts +14 -1
  39. package/dist/entries/app-browser-entry.js +26 -36
  40. package/dist/entries/app-rsc-entry.d.ts +2 -0
  41. package/dist/entries/app-rsc-entry.js +92 -57
  42. package/dist/entries/app-rsc-manifest.d.ts +10 -0
  43. package/dist/entries/app-rsc-manifest.js +20 -1
  44. package/dist/entries/app-ssr-entry.d.ts +4 -1
  45. package/dist/entries/app-ssr-entry.js +9 -2
  46. package/dist/entries/pages-client-entry.d.ts +1 -0
  47. package/dist/entries/pages-client-entry.js +6 -6
  48. package/dist/entries/pages-server-entry.js +17 -14
  49. package/dist/index.d.ts +11 -0
  50. package/dist/index.js +350 -175
  51. package/dist/init.d.ts +1 -1
  52. package/dist/init.js +103 -6
  53. package/dist/plugins/ast-utils.d.ts +53 -2
  54. package/dist/plugins/ast-utils.js +90 -2
  55. package/dist/plugins/cloudflare-dev-module-urls.d.ts +41 -0
  56. package/dist/plugins/cloudflare-dev-module-urls.js +271 -0
  57. package/dist/plugins/commonjs-esm-facade.js +2 -2
  58. package/dist/plugins/css-module-imports.js +13 -20
  59. package/dist/plugins/dynamic-preload-metadata.js +2 -3
  60. package/dist/plugins/extensionless-dynamic-import.js +2 -3
  61. package/dist/plugins/fonts.d.ts +1 -1
  62. package/dist/plugins/fonts.js +3 -3
  63. package/dist/plugins/ignore-dynamic-requests.js +2 -3
  64. package/dist/plugins/import-meta-url.js +3 -4
  65. package/dist/plugins/instrumentation-client.js +3 -2
  66. package/dist/plugins/middleware-export-validation.js +2 -3
  67. package/dist/plugins/og-harfbuzz.js +2 -3
  68. package/dist/plugins/optimize-imports.d.ts +25 -2
  69. package/dist/plugins/optimize-imports.js +109 -24
  70. package/dist/plugins/pages-node-externals.js +2 -3
  71. package/dist/plugins/remove-console.js +2 -18
  72. package/dist/plugins/require-condition-resolution.js +3 -3
  73. package/dist/plugins/require-context.js +2 -3
  74. package/dist/plugins/rsc-client-reference-loaders.d.ts +45 -1
  75. package/dist/plugins/rsc-client-reference-loaders.js +336 -18
  76. package/dist/plugins/strip-server-exports.js +3 -4
  77. package/dist/plugins/styled-jsx.js +2 -3
  78. package/dist/plugins/use-cache-callable.d.ts +26 -2
  79. package/dist/plugins/use-cache-callable.js +101 -36
  80. package/dist/plugins/worker-image-imports.d.ts +1 -0
  81. package/dist/plugins/worker-image-imports.js +31 -34
  82. package/dist/plugins/worker-use-server.js +38 -14
  83. package/dist/routing/app-route-graph.d.ts +1 -1
  84. package/dist/routing/browser-route-manifest.d.ts +43 -0
  85. package/dist/routing/browser-route-manifest.js +195 -0
  86. package/dist/routing/hashed-route-patterns.d.ts +4 -0
  87. package/dist/routing/hashed-route-patterns.js +22 -0
  88. package/dist/routing/optimistic-route-trie.d.ts +27 -0
  89. package/dist/routing/optimistic-route-trie.js +102 -0
  90. package/dist/routing/route-validation.d.ts +6 -1
  91. package/dist/routing/route-validation.js +26 -10
  92. package/dist/server/api-handler.js +1 -1
  93. package/dist/server/app-action-forwarding.d.ts +8 -0
  94. package/dist/server/app-action-forwarding.js +17 -3
  95. package/dist/server/app-browser-entry.js +149 -62
  96. package/dist/server/app-browser-error.d.ts +3 -1
  97. package/dist/server/app-browser-error.js +7 -2
  98. package/dist/server/app-browser-interception-context.d.ts +2 -2
  99. package/dist/server/app-browser-interception-context.js +1 -1
  100. package/dist/server/app-browser-mpa-navigation.d.ts +1 -0
  101. package/dist/server/app-browser-mpa-navigation.js +6 -5
  102. package/dist/server/app-browser-navigation-controller.d.ts +17 -6
  103. package/dist/server/app-browser-navigation-controller.js +88 -26
  104. package/dist/server/app-browser-prefetch-response.js +2 -2
  105. package/dist/server/app-browser-state.d.ts +2 -2
  106. package/dist/server/app-browser-state.js +1 -1
  107. package/dist/server/app-browser-supplemental-refresh.js +1 -1
  108. package/dist/server/app-browser-visible-commit.d.ts +4 -4
  109. package/dist/server/app-client-reference-preloader.d.ts +23 -0
  110. package/dist/server/app-client-reference-preloader.js +30 -7
  111. package/dist/server/app-fallback-renderer.js +2 -1
  112. package/dist/server/app-middleware.d.ts +6 -0
  113. package/dist/server/app-middleware.js +8 -10
  114. package/dist/server/app-optimistic-routing.d.ts +8 -10
  115. package/dist/server/app-optimistic-routing.js +4 -95
  116. package/dist/server/app-page-boundary-render.js +8 -1
  117. package/dist/server/app-page-cache-render.js +1 -0
  118. package/dist/server/app-page-dispatch.js +3 -1
  119. package/dist/server/app-page-render.js +4 -2
  120. package/dist/server/app-page-rsc-render-status.d.ts +1 -0
  121. package/dist/server/app-page-rsc-render-status.js +1 -0
  122. package/dist/server/app-page-search-params-observation.d.ts +1 -4
  123. package/dist/server/app-page-search-params-observation.js +8 -10
  124. package/dist/server/app-page-stream.d.ts +7 -0
  125. package/dist/server/app-page-stream.js +1 -0
  126. package/dist/server/app-pages-bridge.d.ts +2 -1
  127. package/dist/server/app-pages-bridge.js +12 -8
  128. package/dist/server/app-prerender-endpoints.js +1 -1
  129. package/dist/server/app-prerender-static-params.js +3 -2
  130. package/dist/server/app-render-abort-error.d.ts +19 -0
  131. package/dist/server/app-render-abort-error.js +31 -1
  132. package/dist/server/app-render-dependency.js +42 -2
  133. package/dist/server/app-request-stage-independent-entry.js +7 -7
  134. package/dist/server/app-response-stage-entry.js +5 -5
  135. package/dist/server/app-route-handler-dispatch.js +3 -1
  136. package/dist/server/app-route-handler-execution.d.ts +2 -0
  137. package/dist/server/app-route-handler-execution.js +9 -2
  138. package/dist/server/app-route-handler-middleware-context.d.ts +2 -1
  139. package/dist/server/app-route-handler-middleware-context.js +3 -3
  140. package/dist/server/app-route-handler-response.d.ts +2 -1
  141. package/dist/server/app-route-handler-response.js +2 -2
  142. package/dist/server/app-route-handler-runtime.d.ts +2 -0
  143. package/dist/server/app-route-handler-runtime.js +21 -4
  144. package/dist/server/app-route-module-loader.js +7 -6
  145. package/dist/server/app-route-tree.d.ts +20 -0
  146. package/dist/server/app-route-tree.js +18 -0
  147. package/dist/server/app-router-entry.js +7 -7
  148. package/dist/server/app-rsc-cache-busting.d.ts +16 -0
  149. package/dist/server/app-rsc-cache-busting.js +29 -12
  150. package/dist/server/app-rsc-combined-handler.js +8 -1
  151. package/dist/server/app-rsc-errors.d.ts +7 -0
  152. package/dist/server/app-rsc-errors.js +9 -2
  153. package/dist/server/app-rsc-handler.d.ts +4 -1
  154. package/dist/server/app-rsc-handler.js +151 -135
  155. package/dist/server/app-rsc-request-normalization.js +3 -3
  156. package/dist/server/app-rsc-response-finalizer.d.ts +5 -0
  157. package/dist/server/app-rsc-response-finalizer.js +4 -1
  158. package/dist/server/app-rsc-response-stage.js +5 -3
  159. package/dist/server/app-rsc-route-matching.d.ts +1 -0
  160. package/dist/server/app-rsc-route-matching.js +1 -1
  161. package/dist/server/app-server-action-execution.d.ts +23 -6
  162. package/dist/server/app-server-action-execution.js +51 -57
  163. package/dist/server/app-ssr-entry.d.ts +6 -0
  164. package/dist/server/app-ssr-entry.js +21 -11
  165. package/dist/server/app-ssr-stream.d.ts +7 -0
  166. package/dist/server/app-ssr-stream.js +13 -1
  167. package/dist/server/app-visited-response-cache.js +2 -2
  168. package/dist/server/config-headers.js +13 -4
  169. package/dist/server/defer-until-stream-consumed.d.ts +2 -1
  170. package/dist/server/defer-until-stream-consumed.js +3 -1
  171. package/dist/server/dev-server.js +1 -1
  172. package/dist/server/image-optimization.js +1 -0
  173. package/dist/server/isolate-shared-promise.d.ts +10 -0
  174. package/dist/server/isolate-shared-promise.js +33 -0
  175. package/dist/server/isr-cache.js +3 -2
  176. package/dist/server/metadata-route-response.js +2 -2
  177. package/dist/server/middleware-matcher-pattern.d.ts +0 -1
  178. package/dist/server/middleware-matcher-pattern.js +11 -140
  179. package/dist/server/middleware-matcher.js +5 -6
  180. package/dist/server/middleware-response-headers.d.ts +31 -0
  181. package/dist/server/middleware-response-headers.js +57 -1
  182. package/dist/server/middleware-runtime.js +30 -17
  183. package/dist/server/navigation-planner.d.ts +2 -2
  184. package/dist/server/navigation-planner.js +1 -1
  185. package/dist/server/nitro-public-files-plugin.d.ts +38 -0
  186. package/dist/server/nitro-public-files-plugin.js +106 -0
  187. package/dist/server/nitro-public-files.d.ts +21 -0
  188. package/dist/server/nitro-public-files.js +39 -0
  189. package/dist/server/open-redirect.d.ts +11 -4
  190. package/dist/server/open-redirect.js +11 -4
  191. package/dist/server/pages-api-route.js +2 -2
  192. package/dist/server/pages-asset-tags.d.ts +5 -0
  193. package/dist/server/pages-asset-tags.js +9 -2
  194. package/dist/server/pages-client-assets.d.ts +4 -1
  195. package/dist/server/pages-data-route.js +2 -1
  196. package/dist/server/pages-i18n.d.ts +18 -0
  197. package/dist/server/pages-i18n.js +18 -2
  198. package/dist/server/pages-node-compat.d.ts +5 -3
  199. package/dist/server/pages-node-compat.js +35 -16
  200. package/dist/server/pages-page-data.js +1 -1
  201. package/dist/server/pages-page-handler.js +1 -1
  202. package/dist/server/pages-page-response.js +1 -1
  203. package/dist/server/pages-request-pipeline.d.ts +6 -1
  204. package/dist/server/pages-request-pipeline.js +35 -39
  205. package/dist/server/pages-request-stage-entry.js +20 -10
  206. package/dist/server/pages-response-stage-entry.js +1 -1
  207. package/dist/server/pages-revalidate.js +3 -2
  208. package/dist/server/pages-router-entry.js +2 -2
  209. package/dist/server/prod-server.d.ts +2 -2
  210. package/dist/server/prod-server.js +74 -36
  211. package/dist/server/proxy-trust.d.ts +6 -0
  212. package/dist/server/proxy-trust.js +12 -6
  213. package/dist/server/request-pipeline.d.ts +5 -0
  214. package/dist/server/request-pipeline.js +12 -1
  215. package/dist/server/rsc-stream-hints.d.ts +1 -1
  216. package/dist/server/rsc-stream-hints.js +21 -3
  217. package/dist/server/server-reference-loader.js +10 -1
  218. package/dist/server/static-file-cache.js +15 -3
  219. package/dist/server/worker-image-optimization.js +19 -6
  220. package/dist/server/worker-utils.js +1 -1
  221. package/dist/shims/cache-handler.js +3 -2
  222. package/dist/shims/cache-request-state.d.ts +40 -3
  223. package/dist/shims/cache-request-state.js +70 -5
  224. package/dist/shims/cache-runtime.js +47 -19
  225. package/dist/shims/cache.d.ts +2 -2
  226. package/dist/shims/cache.js +17 -8
  227. package/dist/shims/cdn-purge-routes.d.ts +24 -0
  228. package/dist/shims/cdn-purge-routes.js +77 -0
  229. package/dist/shims/dynamic.js +17 -4
  230. package/dist/shims/form.js +8 -3
  231. package/dist/shims/head.js +1 -1
  232. package/dist/shims/headers.js +2 -2
  233. package/dist/shims/image-props.d.ts +93 -0
  234. package/dist/shims/image-props.js +323 -0
  235. package/dist/shims/image.d.ts +4 -18
  236. package/dist/shims/image.js +4 -319
  237. package/dist/shims/internal/headers-state.d.ts +7 -0
  238. package/dist/shims/internal/headers-state.js +14 -2
  239. package/dist/shims/internal/hybrid-client-route-owner-direct.d.ts +4 -1
  240. package/dist/shims/internal/hybrid-client-route-owner-direct.js +32 -15
  241. package/dist/shims/internal/hybrid-client-route-owner.js +9 -8
  242. package/dist/shims/link-prefetch.js +5 -4
  243. package/dist/shims/link.js +7 -5
  244. package/dist/shims/navigation.d.ts +1 -1
  245. package/dist/shims/navigation.js +21 -10
  246. package/dist/shims/og.js +35 -10
  247. package/dist/shims/request-context.d.ts +13 -0
  248. package/dist/shims/router.js +28 -52
  249. package/dist/shims/server.d.ts +42 -8
  250. package/dist/shims/server.js +99 -15
  251. package/dist/shims/thenable-params.d.ts +6 -1
  252. package/dist/shims/thenable-params.js +11 -2
  253. package/dist/shims/unified-request-context.d.ts +5 -0
  254. package/dist/shims/unified-request-context.js +2 -0
  255. package/dist/shims/url-utils.d.ts +7 -0
  256. package/dist/shims/url-utils.js +12 -3
  257. package/dist/utils/asset-prefix.d.ts +7 -0
  258. package/dist/utils/asset-prefix.js +10 -1
  259. package/dist/utils/client-build-manifest.js +12 -5
  260. package/dist/utils/client-runtime-metadata.d.ts +1 -0
  261. package/dist/utils/client-runtime-metadata.js +15 -2
  262. package/dist/utils/domain-locale.js +1 -1
  263. package/dist/utils/lazy-chunks.d.ts +4 -0
  264. package/dist/utils/manifest-paths.d.ts +14 -0
  265. package/dist/utils/manifest-paths.js +22 -1
  266. package/dist/utils/path-to-regexp.d.ts +21 -0
  267. package/dist/{server/middleware-path-to-regexp.js → utils/path-to-regexp.js} +14 -11
  268. package/dist/utils/plugin-react-version.d.ts +15 -0
  269. package/dist/utils/plugin-react-version.js +64 -0
  270. package/dist/utils/plugin-rsc-version.d.ts +2 -0
  271. package/dist/utils/plugin-rsc-version.js +28 -2
  272. package/dist/utils/public-routes.d.ts +2 -0
  273. package/dist/utils/public-routes.js +18 -7
  274. package/dist/utils/react-version.d.ts +7 -0
  275. package/dist/utils/react-version.js +39 -16
  276. package/package.json +6 -6
  277. package/dist/build/nitro-route-rules.d.ts +0 -47
  278. package/dist/build/nitro-route-rules.js +0 -79
  279. package/dist/plugins/cache-flight-codec.d.ts +0 -19
  280. package/dist/plugins/cache-flight-codec.js +0 -68
  281. package/dist/server/middleware-path-to-regexp.d.ts +0 -13
  282. package/dist/utils/regex-safety.d.ts +0 -17
  283. package/dist/utils/regex-safety.js +0 -789
@@ -1,13 +1,13 @@
1
1
  import { VINEXT_PRERENDER_SECRET_HEADER, VINEXT_REVALIDATE_HOST_HEADER } from "../utils/protocol-headers.js";
2
2
  import { requestContextFromRequest } from "../config/request-context.js";
3
- import { assetPrefixPathname, isNextStaticPath } from "../utils/asset-prefix.js";
4
- import { normalizePathnameForRouteMatchStrict } from "../routing/utils.js";
5
3
  import { hasBasePath, stripBasePath } from "../utils/base-path.js";
6
- import { runWithExecutionContext } from "../shims/request-context.js";
7
4
  import { VINEXT_CACHEABILITY_PROBE_QUERY_PARAM, VINEXT_EXPECTED_WORKER_VERSION_HEADER } from "./headers.js";
8
5
  import { notFoundStaticAssetResponse } from "./http-error-responses.js";
9
6
  import { attachRequestCfMetadata, cloneRequestWithHeaders, cloneRequestWithUrl, filterInternalHeaders, guardProtocolRelativeUrl } from "./request-pipeline.js";
10
- import { normalizeDefaultLocalePathname } from "./pages-i18n.js";
7
+ import { assetPrefixPathname, isNextStaticPath } from "../utils/asset-prefix.js";
8
+ import { normalizePathnameForRouteMatchStrict } from "../routing/utils.js";
9
+ import { runWithExecutionContext } from "../shims/request-context.js";
10
+ import { normalizeDefaultLocalePathname, shouldRestoreLocaleRootTrailingSlash } from "./pages-i18n.js";
11
11
  import { isNextDataPathname } from "./pages-data-route.js";
12
12
  import { getExplicitCdnCacheAdapter } from "../shims/cdn-cache-state.js";
13
13
  import { CACHEABILITY_REQUEST_STATE } from "../shims/cacheability-classification.js";
@@ -48,6 +48,10 @@ const pagesRequestStagePrerenderSecret = pagesEntry.prerenderSecret ?? null;
48
48
  const basePath = vinextConfig?.basePath ?? "";
49
49
  const assetPathPrefix = assetPrefixPathname(vinextConfig?.assetPrefix ?? "");
50
50
  const trailingSlash = vinextConfig?.trailingSlash ?? false;
51
+ const localeRootTrailingSlashConfig = {
52
+ trailingSlash,
53
+ skipProxyUrlNormalize: vinextConfig?.skipProxyUrlNormalize
54
+ };
51
55
  const skipTrailingSlashRedirect = vinextConfig?.skipTrailingSlashRedirect ?? false;
52
56
  const i18nConfig = vinextConfig?.i18n ?? null;
53
57
  const configRedirects = vinextConfig?.redirects ?? [];
@@ -88,7 +92,7 @@ function handleRequestStageLocally(request, env, ctx, dispatchResponseStage) {
88
92
  function handleRequest(request, env, platformCtx, dispatchResponseStage, forceCacheBypass, defaultHostRuntime, assets) {
89
93
  const url = new URL(request.url);
90
94
  const trace = async () => {
91
- await pagesEntry.__ensureInstrumentation?.();
95
+ await pagesEntry.__ensureInstrumentation?.(platformCtx);
92
96
  return traceFrameworkRequest({
93
97
  callback: () => handleRequestImpl(request, env, platformCtx, dispatchResponseStage, forceCacheBypass, defaultHostRuntime, assets),
94
98
  getStatus: (response) => response?.status,
@@ -128,7 +132,7 @@ async function handleRequestImpl(request, env, platformCtx, dispatchResponseStag
128
132
  probeRoute = readWorkerCacheabilityProbeRoute(request);
129
133
  const probeUrl = new URL(request.url);
130
134
  probeUrl.searchParams.delete(VINEXT_CACHEABILITY_PROBE_QUERY_PARAM);
131
- request = new Request(probeUrl, request);
135
+ request = cloneRequestWithUrl(request, probeUrl.href);
132
136
  }
133
137
  }
134
138
  let responseStageDispatched = false;
@@ -175,6 +179,7 @@ async function handleRequestImpl(request, env, platformCtx, dispatchResponseStag
175
179
  }
176
180
  const missingBuildAsset = isNextStaticPath(pathname, basePath, assetPathPrefix);
177
181
  const hadBasePath = !basePath || hasBasePath(pathname, basePath);
182
+ const restoreLocaleRootTrailingSlash = shouldRestoreLocaleRootTrailingSlash(pathname, localeRootTrailingSlashConfig);
178
183
  {
179
184
  const stripped = stripBasePath(pathname, basePath);
180
185
  if (stripped !== pathname) {
@@ -193,7 +198,10 @@ async function handleRequestImpl(request, env, platformCtx, dispatchResponseStag
193
198
  request = dataNorm.request;
194
199
  pathname = dataNorm.normalizedPathname;
195
200
  }
196
- const responseStagePolicyPathname = i18nConfig ? normalizeDefaultLocalePathname(pathname, i18nConfig, { hostname: url.hostname }) : pathname;
201
+ const responseStagePolicyPathname = i18nConfig ? normalizeDefaultLocalePathname(pathname, i18nConfig, {
202
+ hostname: url.hostname,
203
+ restoreRootTrailingSlash: restoreLocaleRootTrailingSlash
204
+ }) : pathname;
197
205
  const responseStagePolicyHeaders = resolveResponseStageCachePolicy({
198
206
  basePathState: {
199
207
  basePath,
@@ -219,6 +227,7 @@ async function handleRequestImpl(request, env, platformCtx, dispatchResponseStag
219
227
  hasMiddleware,
220
228
  ctx,
221
229
  recordCacheability: forceCacheBypass,
230
+ restoreLocaleRootTrailingSlash,
222
231
  middlewareRequest: isDataReq && vinextConfig?.skipProxyUrlNormalize ? middlewareRequest : void 0,
223
232
  dataNotFoundResponse: vinextConfig?.skipProxyUrlNormalize ? dataNorm.notFoundResponse : null,
224
233
  authorizeOnDemandRevalidate: typeof authorizeOnDemandRevalidate === "function" ? authorizeOnDemandRevalidate : void 0,
@@ -320,7 +329,7 @@ async function handleRequestImpl(request, env, platformCtx, dispatchResponseStag
320
329
  fetchPublicFile: (sourceRequest) => resolvePublicImageSource(sourceRequest, assets)
321
330
  }), allowedWidths, imageConfig);
322
331
  }
323
- return fetchWorkerFilesystemRoute(filesystemRequest, requestPathname, phase, (assetRequest) => Promise.resolve(assets.fetch(assetRequest)), publicFiles, basePath, assetPathPrefix, hadBasePath);
332
+ return fetchWorkerFilesystemRoute(filesystemRequest, requestPathname, phase, (assetRequest) => Promise.resolve(assets.fetch(assetRequest)), publicFiles, basePath, assetPathPrefix, resolvedPathnameHasBasePath);
324
333
  }
325
334
  };
326
335
  const resolvePublicImageSource = async (sourceRequest, sourceAssets) => {
@@ -333,6 +342,7 @@ async function handleRequestImpl(request, env, platformCtx, dispatchResponseStag
333
342
  const sourceResult = await runPagesRequest(attachRequestCfMetadata(new Request(new URL(sourcePathname + sourceUrl.search, sourceUrl), { signal: sourceRequest.signal }), sourceRequest), {
334
343
  ...deps,
335
344
  hadBasePath: sourceHadBasePath,
345
+ restoreLocaleRootTrailingSlash: shouldRestoreLocaleRootTrailingSlash(sourceUrl.pathname, localeRootTrailingSlashConfig),
336
346
  isDataReq: false,
337
347
  isDataRequest: false,
338
348
  middlewareRequest: void 0,
@@ -341,9 +351,9 @@ async function handleRequestImpl(request, env, platformCtx, dispatchResponseStag
341
351
  runMiddleware: typeof runMiddleware === "function" ? wrapMiddlewareWithBasePath(runMiddleware, basePath, sourceHadBasePath) : null,
342
352
  renderPage: null,
343
353
  handleApi: null,
344
- serveFilesystemRoute: async (candidate, _stagedHeaders, phase, _resolvedUrl, filesystemRequest) => {
354
+ serveFilesystemRoute: async (candidate, _stagedHeaders, phase, _resolvedUrl, filesystemRequest, candidateHasBasePath) => {
345
355
  if (isImageOptimizationPath(candidate)) return false;
346
- const asset = await fetchWorkerFilesystemRoute(filesystemRequest, candidate, phase, (assetRequest) => Promise.resolve(sourceAssets.fetch(assetRequest)), publicFiles, basePath, assetPathPrefix, sourceHadBasePath);
356
+ const asset = await fetchWorkerFilesystemRoute(filesystemRequest, candidate, phase, (assetRequest) => Promise.resolve(sourceAssets.fetch(assetRequest)), publicFiles, basePath, assetPathPrefix, candidateHasBasePath);
347
357
  if (asset === false) return false;
348
358
  sourceAsset = asset;
349
359
  return new Response(null);
@@ -36,7 +36,7 @@ async function renderPagesResponse(request, env, platformCtx, props, stagedHeade
36
36
  if (!isPagesResponseStageProps(props)) return new Response("Invalid vinext Pages response stage", { status: 400 });
37
37
  if (props.buildId !== pagesEntry.buildId) return new Response("Vinext Pages response stage deployment mismatch", { status: 409 });
38
38
  if (props.requestHost !== new URL(request.url).host) return new Response("Invalid vinext Pages response stage", { status: 400 });
39
- await pagesEntry.__ensureInstrumentation?.();
39
+ await pagesEntry.__ensureInstrumentation?.(platformCtx);
40
40
  registerConfiguredImageOptimizer(env);
41
41
  const renderHeaders = new Headers(stagedHeaders ?? props.stagedHeaders ?? []);
42
42
  renderHeaders.delete("Content-Length");
@@ -1,17 +1,18 @@
1
1
  import { PRERENDER_REVALIDATE_HEADER, PRERENDER_REVALIDATE_ONLY_GENERATED_HEADER, VINEXT_REVALIDATE_HOST_HEADER } from "../utils/protocol-headers.js";
2
- import { getRequestExecutionContext } from "../shims/request-context.js";
3
2
  import { VINEXT_REVALIDATED_CACHE_TAG_HEADER } from "./headers.js";
3
+ import { getRequestExecutionContext } from "../shims/request-context.js";
4
+ import { resolveRequestHost, resolveRequestProtocol } from "./proxy-trust.js";
4
5
  import { normalizeDomainHostname } from "../utils/domain-locale.js";
5
6
  import { getCdnCacheAdapter } from "../shims/cdn-cache.js";
6
7
  import { getRevalidateSecret, isOnDemandRevalidateRequest } from "./revalidation-request.js";
7
8
  import "./isr-cache.js";
8
- import { resolveRequestHost, resolveRequestProtocol } from "./proxy-trust.js";
9
9
  //#region src/server/pages-revalidate.ts
10
10
  async function performOnDemandRevalidate(source, urlPath, opts = {}, trustedOrigin, allowedRevalidateHeaderKeys = [], dev = false) {
11
11
  if (typeof urlPath !== "string" || !urlPath.startsWith("/")) throw new Error(`Invalid urlPath provided to revalidate(), must be a path e.g. /blog/post-1, received ${urlPath}`);
12
12
  if (isSourceRevalidationRequest(source)) throw new Error(`Cannot revalidate ${urlPath} from an internal revalidation request`);
13
13
  const executionContext = getRequestExecutionContext();
14
14
  const dispatchRevalidate = executionContext?.dispatchPagesRevalidate;
15
+ if (!dispatchRevalidate && !trustedOrigin) throw new Error(`Cannot revalidate ${urlPath}: no in-process dispatcher or server-owned origin is available`);
15
16
  const target = createRevalidateTarget(source, urlPath, trustedOrigin);
16
17
  const headers = { [PRERENDER_REVALIDATE_HEADER]: getRevalidateSecret() };
17
18
  if (trustedOrigin && !dispatchRevalidate) {
@@ -1,6 +1,6 @@
1
- import { runWithExecutionContext } from "../shims/request-context.js";
2
1
  import { VINEXT_CACHEABILITY_PROBE_HEADER, VINEXT_CACHEABILITY_PROBE_QUERY_PARAM } from "./headers.js";
3
2
  import { cloneRequestWithHeaders, cloneRequestWithUrl } from "./request-pipeline.js";
3
+ import { runWithExecutionContext } from "../shims/request-context.js";
4
4
  import { getCdnCacheAdapter } from "../shims/cdn-cache.js";
5
5
  import { validateCdnRequest } from "./cache-control.js";
6
6
  import { createWorkerRevalidationContext } from "./worker-revalidation-context.js";
@@ -20,7 +20,7 @@ async function handleSingleStageRequest(request, env, platformCtx) {
20
20
  let ctx = createWorkerPrerenderDiscoveryContext(ctxWithRevalidation, request, pagesRequestStagePrerenderSecret);
21
21
  const readinessResponse = createWorkerPrerenderReadinessResponse(ctx, request);
22
22
  if (readinessResponse) {
23
- if (readinessResponse.status === 204) await Promise.all([__ensureInstrumentation(), __ensureInstrumentation$1()]);
23
+ if (readinessResponse.status === 204) await Promise.all([__ensureInstrumentation(ctx), __ensureInstrumentation$1(ctx)]);
24
24
  return await validateCdnRequest(request) ?? readinessResponse;
25
25
  }
26
26
  const isClientBuildFile = isPagesClientBuildFileRequest(request, env, ctx);
@@ -3,7 +3,7 @@ import { negotiateEncoding } from "./accept-encoding.js";
3
3
  import { StaticFileCache } from "./static-file-cache.js";
4
4
  import { resolveRequestHost, trustProxy, trustedHosts } from "./proxy-trust.js";
5
5
  import { COMPRESS_THRESHOLD, isCompressibleContentType } from "./response-compression.js";
6
- import { IncomingMessage, ServerResponse } from "node:http";
6
+ import { IncomingMessage, Server, ServerResponse } from "node:http";
7
7
  //#region src/server/prod-server.d.ts
8
8
  /**
9
9
  * Import a built server entry module (App Router RSC entry or Pages Router
@@ -127,7 +127,7 @@ declare function waitForNodeResponseCompletion(res: ServerResponse): Promise<voi
127
127
  * Pages Router (dist/server/entry.js) and configures the appropriate handler.
128
128
  */
129
129
  export declare function startProdServer(options?: ProdServerOptions): Promise<{
130
- server: import("node:http").Server<typeof IncomingMessage, typeof ServerResponse>;
130
+ server: Server<typeof IncomingMessage, typeof ServerResponse>;
131
131
  port: number;
132
132
  }>;
133
133
  type AppRouterPrerenderSeeder = (serverDir: string) => Promise<number>;
@@ -1,22 +1,23 @@
1
1
  import path from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
2
2
  import { isUnknownRecord } from "../utils/record.js";
3
3
  import { VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER, VINEXT_PRERENDER_SPECULATIVE_HEADER } from "../utils/protocol-headers.js";
4
- import { ASSET_PREFIX_URL_DIR, assetPrefixPathname, isAbsoluteAssetPrefix } from "../utils/asset-prefix.js";
5
- import { StaticFileCache, contentTypeForPath, etagFromFilenameHash } from "./static-file-cache.js";
6
- import { normalizePathnameForRouteMatchStrict } from "../routing/utils.js";
7
4
  import { hasBasePath, stripBasePath } from "../utils/base-path.js";
8
5
  import { VINEXT_PRERENDER_RENDER_ERROR_HEADER, VINEXT_PRERENDER_SPECIAL_ERROR_HEADER } from "./headers.js";
9
- import { normalizePath } from "./normalize-path.js";
10
6
  import { notFoundResponse } from "./http-error-responses.js";
11
7
  import { getRepeatedSlashRedirect, isOpenRedirectShaped, sendRepeatedSlashRedirect } from "./open-redirect.js";
12
8
  import { readStaticFileSignal } from "./static-file-signal.js";
13
9
  import { canonicalizeRequestPathname, filterInternalHeaders } from "./request-pipeline.js";
10
+ import { ASSET_PREFIX_URL_DIR, assetPrefixPathname, isAbsoluteAssetPrefix, isAssetPrefixBuildAsset } from "../utils/asset-prefix.js";
11
+ import { StaticFileCache, contentTypeForPath, etagFromFilenameHash } from "./static-file-cache.js";
12
+ import { normalizePathnameForRouteMatchStrict } from "../routing/utils.js";
13
+ import { resolveRequestHost, resolveRequestProtocol, resolveTrustedForwardedHost, trustProxy, trustedHosts } from "./proxy-trust.js";
14
+ import { normalizePath } from "./normalize-path.js";
15
+ import { shouldRestoreLocaleRootTrailingSlash } from "./pages-i18n.js";
14
16
  import { buildNextDataNotFoundResponse, encodeUrlParserIgnoredCharacters, isNextDataPathname, normalizeNextDataPagePathname, parseNextDataPathname, shouldAddTrailingSlashToPagesDataPath, urlParserCreatesPagesDataPath } from "./pages-data-route.js";
15
17
  import { buildCacheStateHeaders } from "./cache-headers.js";
16
18
  import { parseHttpDate } from "./http-date.js";
17
19
  import { evaluateStaticPreconditions } from "./http-conditional.js";
18
20
  import { setPagesClientAssets } from "./pages-client-assets.js";
19
- import { resolveRequestHost, resolveRequestProtocol, trustProxy, trustedHosts } from "./proxy-trust.js";
20
21
  import { signalFromNodeResponse } from "./node-response-signal.js";
21
22
  import { DEFAULT_DEVICE_SIZES, DEFAULT_IMAGE_SIZES, IMAGE_RESPONSE_CACHE_STATE, INVALID_IMAGE_SOURCE_MESSAGE, isImageOptimizationPath, isImageSourceBodyStatus, isSafeImageContentType, parseImageParams, readImageOptimizationSignal } from "./image-optimization.js";
22
23
  import { installSocketErrorBackstop } from "./socket-error-backstop.js";
@@ -378,6 +379,19 @@ function isVinextStreamedHtmlResponse(response) {
378
379
  function isVinextStreamedApiResponse(response) {
379
380
  return response.__vinextStreamedApiResponse === true;
380
381
  }
382
+ function disablePrerenderKeepAliveTimeout(server, purpose) {
383
+ if (purpose === "prerender") server.keepAliveTimeout = 0;
384
+ }
385
+ function listen(server, port, host) {
386
+ return new Promise((resolve, reject) => {
387
+ server.once("error", reject);
388
+ server.listen(port, host, () => {
389
+ server.off("error", reject);
390
+ const addr = server.address();
391
+ resolve(typeof addr === "object" && addr ? addr.port : port);
392
+ });
393
+ });
394
+ }
381
395
  function logProdServerStarted(host, port, purpose) {
382
396
  const url = `http://${host}:${port}`;
383
397
  if (purpose === "prerender") {
@@ -925,14 +939,16 @@ async function startProdServer(options = {}) {
925
939
  silent
926
940
  });
927
941
  }
928
- function createNodeExecutionContext(trustedRevalidateOrigin) {
942
+ function createNodeExecutionContext(trustedRevalidateOrigin, { middlewareOrigin, requestSignal } = {}) {
929
943
  return {
930
944
  hostRuntime: "node",
945
+ requestSignal,
931
946
  waitUntil(promise) {
932
947
  Promise.resolve(promise).catch(() => {});
933
948
  },
934
949
  passThroughOnException() {},
935
- trustedRevalidateOrigin
950
+ trustedRevalidateOrigin,
951
+ middlewareOrigin
936
952
  };
937
953
  }
938
954
  /**
@@ -953,8 +969,26 @@ function markPrerenderSpecialError(response, marker) {
953
969
  });
954
970
  }
955
971
  function resolveTrustedNodeRevalidateOrigin(req, configuredHost, configuredPort) {
972
+ return `http://${resolveNodeServerHost(req, configuredHost, configuredPort)}`;
973
+ }
974
+ /**
975
+ * The origin middleware runs against. The Host header is client-controlled,
976
+ * so, like Next.js, which builds the middleware URL from its own hostname and
977
+ * port, it never counts as the server's origin. Otherwise a client could send
978
+ * the host of an external middleware rewrite target and turn that rewrite into
979
+ * an internal one, skipping middleware's checks for the target path. A trusted
980
+ * `X-Forwarded-Host` is operator-approved, so it keeps the request origin, and
981
+ * rewrites to that host stay internal.
982
+ */
983
+ function resolveNodeMiddlewareOrigin(req, requestUrl, configuredHost, configuredPort) {
984
+ const url = new URL(requestUrl);
985
+ if (resolveTrustedForwardedHost(req) !== void 0) return url.origin;
986
+ return `${url.protocol}//${resolveNodeServerHost(req, configuredHost, configuredPort)}`;
987
+ }
988
+ /** The `host:port` this server is reachable at locally. */
989
+ function resolveNodeServerHost(req, configuredHost, configuredPort) {
956
990
  const port = req.socket.localPort ?? configuredPort;
957
- return `http://${normalizeInternalFetchHost(configuredHost)}:${port}`;
991
+ return `${normalizeInternalFetchHost(configuredHost)}:${port}`;
958
992
  }
959
993
  function normalizeInternalFetchHost(host) {
960
994
  if (!host || host === "0.0.0.0" || host === "::") return "localhost";
@@ -1058,6 +1092,7 @@ function installPagesClientAssets(options) {
1058
1092
  clientEntry: metadata.clientEntryFile,
1059
1093
  appBootstrapPreinitModules: metadata.appBootstrapPreinitModules,
1060
1094
  ssrManifest: Object.keys(ssrManifest).length > 0 ? ssrManifest : void 0,
1095
+ sharedChunks: metadata.sharedChunks,
1061
1096
  cssGraph: metadata.cssGraph,
1062
1097
  lazyChunks: metadata.lazyChunks,
1063
1098
  dynamicPreloads: metadata.dynamicPreloads,
@@ -1154,7 +1189,7 @@ async function startAppRouterServer(options) {
1154
1189
  const assetLookupPath = sourcePathname !== null ? resolveAppRouterAssetPath(sourcePathname, appAssetPathPrefix, appRouterAssetPrefix) : null;
1155
1190
  if (assetLookupPath && await serveSource(assetLookupPath)) return;
1156
1191
  if (sourcePathname !== null) {
1157
- const sourceResponse = await rscHandler(new Request(sourceUrl, { signal: request.signal }), createNodeExecutionContext(resolveTrustedNodeRevalidateOrigin(req, host, port)));
1192
+ const sourceResponse = await rscHandler(new Request(sourceUrl, { signal: request.signal }), createNodeExecutionContext(resolveTrustedNodeRevalidateOrigin(req, host, port), { middlewareOrigin: resolveNodeMiddlewareOrigin(req, request.url, host, port) }));
1158
1193
  const sourceSignal = isImageSourceBodyStatus(sourceResponse.status) ? readStaticFileSignal(sourceResponse) : null;
1159
1194
  cancelResponseBody(sourceResponse, request.signal.reason);
1160
1195
  if (request.signal.aborted) return;
@@ -1211,8 +1246,12 @@ async function startAppRouterServer(options) {
1211
1246
  if (clientBuildFile && await tryServeStatic(req, res, clientDir, clientBuildFile, compress, staticCache)) return;
1212
1247
  }
1213
1248
  try {
1214
- const request = nodeToWebRequest(req, rawUrl, prerenderSecret, appRouterI18nConfig, appRouterAuthorizeOnDemandRevalidate, signalFromNodeResponse(res));
1215
- const ctx = createNodeExecutionContext(resolveTrustedNodeRevalidateOrigin(req, host, port));
1249
+ const signal = signalFromNodeResponse(res);
1250
+ const request = nodeToWebRequest(req, rawUrl, prerenderSecret, appRouterI18nConfig, appRouterAuthorizeOnDemandRevalidate, signal);
1251
+ const ctx = createNodeExecutionContext(resolveTrustedNodeRevalidateOrigin(req, host, port), {
1252
+ middlewareOrigin: resolveNodeMiddlewareOrigin(req, request.url, host, port),
1253
+ requestSignal: signal
1254
+ });
1216
1255
  const recorded = {};
1217
1256
  if (purpose === "prerender") ctx.recordPrerenderSpecialError = (marker) => {
1218
1257
  recorded.marker = marker;
@@ -1282,18 +1321,12 @@ async function startAppRouterServer(options) {
1282
1321
  const server = createServer((req, res) => {
1283
1322
  runWithServerEntryRequire(rscEntryRequire, () => handleRequest(req, res));
1284
1323
  });
1285
- await new Promise((resolve) => {
1286
- server.listen(port, host, () => {
1287
- const addr = server.address();
1288
- const actualPort = typeof addr === "object" && addr ? addr.port : port;
1289
- if (!silent) logProdServerStarted(host, actualPort, purpose);
1290
- resolve();
1291
- });
1292
- });
1293
- const addr = server.address();
1324
+ disablePrerenderKeepAliveTimeout(server, purpose);
1325
+ const actualPort = await listen(server, port, host);
1326
+ if (!silent) logProdServerStarted(host, actualPort, purpose);
1294
1327
  return {
1295
1328
  server,
1296
- port: typeof addr === "object" && addr ? addr.port : port
1329
+ port: actualPort
1297
1330
  };
1298
1331
  }
1299
1332
  function isPagesServerEntryPageRoute(value) {
@@ -1323,18 +1356,12 @@ async function startPagesRouterServer(options) {
1323
1356
  const { port, host, purpose, silent } = options;
1324
1357
  const handler = await createPagesRouterRequestHandler(options);
1325
1358
  const server = createServer(handler);
1326
- await new Promise((resolve) => {
1327
- server.listen(port, host, () => {
1328
- const addr = server.address();
1329
- const actualPort = typeof addr === "object" && addr ? addr.port : port;
1330
- if (!silent) logProdServerStarted(host, actualPort, purpose);
1331
- resolve();
1332
- });
1333
- });
1334
- const addr = server.address();
1359
+ disablePrerenderKeepAliveTimeout(server, purpose);
1360
+ const actualPort = await listen(server, port, host);
1361
+ if (!silent) logProdServerStarted(host, actualPort, purpose);
1335
1362
  return {
1336
1363
  server,
1337
- port: typeof addr === "object" && addr ? addr.port : port
1364
+ port: actualPort
1338
1365
  };
1339
1366
  }
1340
1367
  /**
@@ -1481,6 +1508,10 @@ async function createPagesRouterRequestHandler(options) {
1481
1508
  }
1482
1509
  try {
1483
1510
  const hadBasePath = !basePath || hasBasePath(requestPathname, basePath);
1511
+ const restoreLocaleRootTrailingSlash = shouldRestoreLocaleRootTrailingSlash(requestPathname, {
1512
+ trailingSlash,
1513
+ skipProxyUrlNormalize
1514
+ });
1484
1515
  let configMatchPathname = stripBasePath(requestPathname, basePath);
1485
1516
  {
1486
1517
  const strippedPathname = stripBasePath(pathname, basePath);
@@ -1543,6 +1574,8 @@ async function createPagesRouterRequestHandler(options) {
1543
1574
  duplex: hasBody ? "half" : void 0
1544
1575
  });
1545
1576
  const middlewareRequest = isDataReq && skipProxyUrlNormalize ? new Request(new URL(originalRenderUrl, webRequest.url), webRequest) : void 0;
1577
+ const middlewareCtx = createNodeExecutionContext(void 0, { middlewareOrigin: resolveNodeMiddlewareOrigin(req, webRequest.url, host, port) });
1578
+ const runNodeMiddleware = typeof runMiddleware === "function" ? (request, _ctx, opts) => runMiddleware(request, middlewareCtx, opts) : null;
1546
1579
  const resolvePublicImageSource = async (sourceUrl) => {
1547
1580
  const rawSourcePathname = sourceUrl.pathname;
1548
1581
  if (getRepeatedSlashRedirect(rawSourcePathname) || isOpenRedirectShaped(rawSourcePathname)) return null;
@@ -1561,11 +1594,15 @@ async function createPagesRouterRequestHandler(options) {
1561
1594
  recordCacheability: false,
1562
1595
  rawSearch: sourceUrl.search,
1563
1596
  configMatchPathname: strippedSourcePathname,
1564
- runMiddleware: typeof runMiddleware === "function" ? wrapMiddlewareWithBasePath(runMiddleware, basePath, sourceHadBasePath) : null,
1597
+ restoreLocaleRootTrailingSlash: shouldRestoreLocaleRootTrailingSlash(sourceRequestPathname, {
1598
+ trailingSlash,
1599
+ skipProxyUrlNormalize
1600
+ }),
1601
+ runMiddleware: runNodeMiddleware ? wrapMiddlewareWithBasePath(runNodeMiddleware, basePath, sourceHadBasePath) : null,
1565
1602
  renderPage: null,
1566
1603
  handleApi: null,
1567
- serveFilesystemRoute: async (candidate, _stagedHeaders, phase) => {
1568
- if (isImageOptimizationPath(candidate) || isPagesFilesystemExcludedPath(candidate, phase)) return false;
1604
+ serveFilesystemRoute: async (candidate, _stagedHeaders, phase, _resolvedUrl, _request, candidateHasBasePath) => {
1605
+ if (!candidateHasBasePath && !isAssetPrefixBuildAsset(candidate, pagesAssetPathPrefix) || isImageOptimizationPath(candidate) || isPagesFilesystemExcludedPath(candidate, phase)) return false;
1569
1606
  const lookupPath = staticCacheLookupPath(candidate);
1570
1607
  if (lookupPath === null || lookupPath === "/" || !staticCache.lookup(lookupPath)) return false;
1571
1608
  sourcePath = candidate;
@@ -1595,9 +1632,10 @@ async function createPagesRouterRequestHandler(options) {
1595
1632
  rawSearch: rawQs,
1596
1633
  authorizeOnDemandRevalidate: typeof authorizeOnDemandRevalidate === "function" ? authorizeOnDemandRevalidate : void 0,
1597
1634
  configMatchPathname,
1635
+ restoreLocaleRootTrailingSlash,
1598
1636
  matchPageRoute: matchPageRoute ?? null,
1599
1637
  matchApiRoute: matchApiRoute ?? null,
1600
- runMiddleware: typeof runMiddleware === "function" ? wrapMiddlewareWithBasePath(runMiddleware, basePath, hadBasePath) : null,
1638
+ runMiddleware: runNodeMiddleware ? wrapMiddlewareWithBasePath(runNodeMiddleware, basePath, hadBasePath) : null,
1601
1639
  renderPage: typeof renderPage === "function" ? (request, resolvedUrl, options, stagedHeaders) => renderPage(request, resolvedUrl, ssrManifest, void 0, stagedHeaders, {
1602
1640
  ...options,
1603
1641
  originalUrl: originalRenderUrl
@@ -1648,7 +1686,7 @@ async function createPagesRouterRequestHandler(options) {
1648
1686
  res.end(INVALID_IMAGE_SOURCE_MESSAGE);
1649
1687
  return true;
1650
1688
  }
1651
- if (isPagesFilesystemExcludedPath(requestPathname, phase)) return false;
1689
+ if (!resolvedPathnameHasBasePath && !isAssetPrefixBuildAsset(requestPathname, pagesAssetPathPrefix) || isPagesFilesystemExcludedPath(requestPathname, phase)) return false;
1652
1690
  return tryServeStatic(req, res, clientDir, requestPathname, compress, staticCache, stagedHeaders);
1653
1691
  }
1654
1692
  };
@@ -35,4 +35,10 @@ export declare function resolveRequestProtocol(source: IncomingMessage | Headers
35
35
  * against `request.url`.
36
36
  */
37
37
  export declare function resolveRequestHost(source: IncomingMessage | Headers, fallback: string): string;
38
+ /**
39
+ * The `X-Forwarded-Host` value when it matches the `trustedHosts` allow-list,
40
+ * otherwise undefined. Unlike the raw `Host` header, this host is
41
+ * operator-approved.
42
+ */
43
+ export declare function resolveTrustedForwardedHost(source: IncomingMessage | Headers): string | undefined;
38
44
  //#endregion
@@ -42,12 +42,18 @@ function resolveRequestProtocol(source) {
42
42
  * against `request.url`.
43
43
  */
44
44
  function resolveRequestHost(source, fallback) {
45
+ return resolveTrustedForwardedHost(source) ?? (readHost(source) || fallback);
46
+ }
47
+ /**
48
+ * The `X-Forwarded-Host` value when it matches the `trustedHosts` allow-list,
49
+ * otherwise undefined. Unlike the raw `Host` header, this host is
50
+ * operator-approved.
51
+ */
52
+ function resolveTrustedForwardedHost(source) {
45
53
  const rawForwarded = readForwardedHost(source);
46
- if (rawForwarded && trustedHosts.size > 0) {
47
- const forwardedHost = rawForwarded.split(",")[0]?.trim().toLowerCase();
48
- if (forwardedHost && trustedHosts.has(forwardedHost)) return forwardedHost;
49
- }
50
- return readHost(source) || fallback;
54
+ if (!rawForwarded || trustedHosts.size === 0) return void 0;
55
+ const forwardedHost = rawForwarded.split(",")[0]?.trim().toLowerCase();
56
+ return forwardedHost && trustedHosts.has(forwardedHost) ? forwardedHost : void 0;
51
57
  }
52
58
  function readForwardedProto(source) {
53
59
  if (isWebHeaders(source)) return source.get("x-forwarded-proto") ?? void 0;
@@ -65,4 +71,4 @@ function isWebHeaders(source) {
65
71
  return typeof source.get === "function";
66
72
  }
67
73
  //#endregion
68
- export { resolveRequestHost, resolveRequestProtocol, trustProxy, trustedHosts };
74
+ export { resolveRequestHost, resolveRequestProtocol, resolveTrustedForwardedHost, trustProxy, trustedHosts };
@@ -143,6 +143,11 @@ export declare function isOriginAllowed(origin: string, allowed: string[]): bool
143
143
  *
144
144
  * @param headers - The Headers object to modify in place
145
145
  */
146
+ /**
147
+ * Next.js drops each empty middleware Set-Cookie value when it converts
148
+ * middleware's response headers, so blank values never reach the response.
149
+ */
150
+ export declare function dropEmptyMiddlewareSetCookie(headers: Headers): void;
146
151
  export declare function processMiddlewareHeaders(headers: Headers): void;
147
152
  /**
148
153
  * Strip internal headers from an inbound request so they cannot be forged by
@@ -313,7 +313,18 @@ function isOriginAllowed(origin, allowed) {
313
313
  *
314
314
  * @param headers - The Headers object to modify in place
315
315
  */
316
+ /**
317
+ * Next.js drops each empty middleware Set-Cookie value when it converts
318
+ * middleware's response headers, so blank values never reach the response.
319
+ */
320
+ function dropEmptyMiddlewareSetCookie(headers) {
321
+ const cookies = headers.getSetCookie();
322
+ if (!cookies.includes("")) return;
323
+ headers.delete("set-cookie");
324
+ for (const cookie of cookies) if (cookie) headers.append("set-cookie", cookie);
325
+ }
316
326
  function processMiddlewareHeaders(headers) {
327
+ dropEmptyMiddlewareSetCookie(headers);
317
328
  const keysToDelete = [];
318
329
  const unconsumedRequestHeaders = getUnconsumedMiddlewareRequestHeaders(headers);
319
330
  for (const key of headers.keys()) if (key.startsWith("x-middleware-") && key !== "x-middleware-cache" && !unconsumedRequestHeaders.has(key)) keysToDelete.push(key);
@@ -433,4 +444,4 @@ function cloneRequestWithUrl(request, url) {
433
444
  return attachRequestCfMetadata(cloned, request);
434
445
  }
435
446
  //#endregion
436
- export { INTERNAL_HEADERS, VINEXT_INTERNAL_HEADERS, attachRequestCfMetadata, canonicalizeRequestPathname, canonicalizeRequestUrlPathname, cloneRequestWithHeaders, cloneRequestWithUrl, createStaticFileSignal, filterInternalHeaders, getRepeatedSlashRedirect, guardProtocolRelativeUrl, hasBasePath, isOpenRedirectShaped, isOriginAllowed, normalizeTrailingSlash, normalizeTrailingSlashPathname, processMiddlewareHeaders, resolvePublicFileRoute, sendRepeatedSlashRedirect, stripBasePath, validateCsrfOrigin, validateServerActionPayload };
447
+ export { INTERNAL_HEADERS, VINEXT_INTERNAL_HEADERS, attachRequestCfMetadata, canonicalizeRequestPathname, canonicalizeRequestUrlPathname, cloneRequestWithHeaders, cloneRequestWithUrl, createStaticFileSignal, dropEmptyMiddlewareSetCookie, filterInternalHeaders, getRepeatedSlashRedirect, guardProtocolRelativeUrl, hasBasePath, isOpenRedirectShaped, isOriginAllowed, normalizeTrailingSlash, normalizeTrailingSlashPathname, processMiddlewareHeaders, resolvePublicFileRoute, sendRepeatedSlashRedirect, stripBasePath, validateCsrfOrigin, validateServerActionPayload };
@@ -11,7 +11,7 @@
11
11
  * tag is `HL` are decoded and inspected. Length-prefixed bodies remain separate
12
12
  * so binary bytes do not force adjacent text through the embed's base64 path.
13
13
  */
14
- export declare function normalizeReactFlightPreloadHints(stream: ReadableStream<Uint8Array>): ReadableStream<Uint8Array>;
14
+ export declare function normalizeReactFlightPreloadHints(stream: ReadableStream<Uint8Array>, onCancel?: (reason: unknown) => void): ReadableStream<Uint8Array>;
15
15
  export type RscRawRenderer = (model: unknown, options?: unknown) => ReadableStream<Uint8Array>;
16
16
  export type RscRawPrerenderer = (model: unknown, options?: unknown) => Promise<{
17
17
  prelude: ReadableStream<Uint8Array>;
@@ -1,3 +1,4 @@
1
+ import { createRenderStreamCancellation } from "./app-render-abort-error.js";
1
2
  //#region src/server/rsc-stream-hints.ts
2
3
  const REACT_FLIGHT_STYLESHEET_PRELOAD_HINT = /^([0-9a-f]*:HL\[.*?),"stylesheet"(\]|,)/;
3
4
  const STYLESHEET_TO_STYLE_JSON_PADDING = " ".repeat(5);
@@ -106,7 +107,7 @@ function isTagInTable(table, byte) {
106
107
  * tag is `HL` are decoded and inspected. Length-prefixed bodies remain separate
107
108
  * so binary bytes do not force adjacent text through the embed's base64 path.
108
109
  */
109
- function normalizeReactFlightPreloadHints(stream) {
110
+ function normalizeReactFlightPreloadHints(stream, onCancel) {
110
111
  let carry = null;
111
112
  let rawBytesRemaining = 0;
112
113
  let passThrough = false;
@@ -194,11 +195,28 @@ function normalizeReactFlightPreloadHints(stream) {
194
195
  },
195
196
  flush(controller) {
196
197
  if (carry !== null && carry.byteLength > 0) controller.enqueue(rawBytesRemaining > 0 ? carry : normalizeReactFlightHintLine(carry));
197
- }
198
+ },
199
+ cancel: onCancel
198
200
  }));
199
201
  }
200
202
  function createRscRenderer(render) {
201
- return (model, options) => normalizeReactFlightPreloadHints(render(model, options));
203
+ return (model, options) => {
204
+ const cancellation = createRenderStreamCancellation();
205
+ return normalizeReactFlightPreloadHints(render(model, ignoreCancellationErrors(options, cancellation)), cancellation.record);
206
+ };
207
+ }
208
+ /** A consumer cancelling the payload is not a render failure. */
209
+ function ignoreCancellationErrors(options, cancellation) {
210
+ if (!options || typeof options !== "object") return options;
211
+ const onError = Reflect.get(options, "onError");
212
+ if (typeof onError !== "function") return options;
213
+ return {
214
+ ...options,
215
+ onError(error, ...rest) {
216
+ if (cancellation.isReason(error)) return void 0;
217
+ return Reflect.apply(onError, options, [error, ...rest]);
218
+ }
219
+ };
202
220
  }
203
221
  function createRscPrerenderer(prerender) {
204
222
  return async (model, options) => {
@@ -1,4 +1,6 @@
1
1
  import { runOutsideRequestScopes } from "../shims/internal/als-registry.js";
2
+ import { getRequestExecutionContext } from "../shims/request-context.js";
3
+ import { shareIsolatePromise } from "./isolate-shared-promise.js";
2
4
  //#region src/server/server-reference-loader.ts
3
5
  /**
4
6
  * Keep server-reference module evaluation out of the request that first
@@ -21,7 +23,14 @@ const ISOLATED = Symbol.for("vinext.serverReferenceRequire.isolated");
21
23
  function isolateServerReferenceLoads() {
22
24
  const load = globalThis.__vite_rsc_server_require__;
23
25
  if (typeof load !== "function" || ISOLATED in load) return;
24
- const isolated = (id) => runOutsideRequestScopes(() => load(id));
26
+ const started = /* @__PURE__ */ new WeakSet();
27
+ const isolated = (id) => {
28
+ const ctx = getRequestExecutionContext();
29
+ const loaded = runOutsideRequestScopes(() => load(id));
30
+ if (!(loaded instanceof Promise) || started.has(loaded)) return loaded;
31
+ started.add(loaded);
32
+ return shareIsolatePromise(loaded, ctx);
33
+ };
25
34
  Object.defineProperty(isolated, ISOLATED, { value: true });
26
35
  globalThis.__vite_rsc_server_require__ = isolated;
27
36
  }
@@ -178,6 +178,15 @@ var StaticFileCache = class StaticFileCache {
178
178
  return this.entries.get(pathname);
179
179
  }
180
180
  };
181
+ const MANAGED_CHUNKS_SEGMENT = `${ASSET_PREFIX_URL_DIR}/chunks/`;
182
+ const MANAGED_CSS_SEGMENT = `${ASSET_PREFIX_URL_DIR}/css/`;
183
+ const MANAGED_WORKERS_SEGMENT = `${ASSET_PREFIX_URL_DIR}/workers/`;
184
+ const MANAGED_MEDIA_SEGMENT = `${ASSET_PREFIX_URL_DIR}/media/`;
185
+ const HASH_ONLY_BASENAME_RE = /^[A-Za-z0-9_-]{8}$/;
186
+ const WORKER_BASENAME_RE = /^[0-9a-f]{8}-[A-Za-z0-9_-]{8}$/;
187
+ function isInManagedDir(normalizedPath, segment) {
188
+ return normalizedPath.startsWith(segment) || normalizedPath.includes(`/${segment}`);
189
+ }
181
190
  /**
182
191
  * Extract a stable weak ETag from a Vite hashed filename (e.g. `app-DqZc3R4n.js`).
183
192
  * The hash is a content hash computed by the bundler — deterministic across
@@ -190,14 +199,17 @@ var StaticFileCache = class StaticFileCache {
190
199
  */
191
200
  function etagFromFilenameHash(relativePath, ext) {
192
201
  const basename = path.basename(relativePath, ext);
202
+ if (basename.length === 8 && HASH_ONLY_BASENAME_RE.test(basename)) {
203
+ const normalizedPath = toSlash(relativePath);
204
+ if (isInManagedDir(normalizedPath, MANAGED_CHUNKS_SEGMENT) || isInManagedDir(normalizedPath, MANAGED_CSS_SEGMENT)) return `W/"${basename}"`;
205
+ }
206
+ if (basename.length === 17 && WORKER_BASENAME_RE.test(basename) && isInManagedDir(toSlash(relativePath), MANAGED_WORKERS_SEGMENT)) return `W/"${basename}"`;
193
207
  const lastDash = basename.lastIndexOf("-");
194
208
  if (lastDash !== -1 && lastDash !== basename.length - 1) {
195
209
  const suffix = basename.slice(lastDash + 1);
196
210
  if (suffix.length >= 6 && suffix.length <= 12 && /^[A-Za-z0-9_-]+$/.test(suffix)) return `W/"${suffix}"`;
197
211
  }
198
- const normalizedPath = toSlash(relativePath);
199
- const managedMediaSegment = `${ASSET_PREFIX_URL_DIR}/media/`;
200
- if (normalizedPath.startsWith(managedMediaSegment) || normalizedPath.includes(`/${managedMediaSegment}`)) {
212
+ if (isInManagedDir(toSlash(relativePath), MANAGED_MEDIA_SEGMENT)) {
201
213
  const lastDot = basename.lastIndexOf(".");
202
214
  if (lastDot !== -1) {
203
215
  const suffix = basename.slice(lastDot + 1);