astro 7.2.2 → 7.2.4

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 (158) hide show
  1. package/dist/actions/handler.d.ts +6 -12
  2. package/dist/actions/handler.js +30 -40
  3. package/dist/actions/load.d.ts +12 -0
  4. package/dist/actions/load.js +55 -0
  5. package/dist/actions/runtime/entrypoints/server.js +5 -4
  6. package/dist/actions/runtime/server.js +8 -6
  7. package/dist/assets/fonts/providers/index.d.ts +1 -1
  8. package/dist/assets/fonts/providers/index.js +2 -12
  9. package/dist/assets/utils/vendor/image-size/types/heif.js +8 -3
  10. package/dist/assets/utils/vendor/image-size/types/icns.js +10 -2
  11. package/dist/assets/utils/vendor/image-size/types/jp2.js +2 -2
  12. package/dist/assets/utils/vendor/image-size/types/jxl.js +5 -2
  13. package/dist/assets/utils/vendor/image-size/types/utils.d.ts +1 -1
  14. package/dist/assets/utils/vendor/image-size/types/utils.js +20 -6
  15. package/dist/cli/infra/build-time-astro-version-provider.js +1 -1
  16. package/dist/container/environment.d.ts +20 -0
  17. package/dist/container/environment.js +106 -0
  18. package/dist/container/index.js +73 -37
  19. package/dist/content/content-layer.js +3 -3
  20. package/dist/content/data-store-writer.d.ts +7 -10
  21. package/dist/content/data-store-writer.js +62 -27
  22. package/dist/content/data-store.d.ts +20 -3
  23. package/dist/content/data-store.js +28 -7
  24. package/dist/content/mutable-data-store.js +15 -10
  25. package/dist/content/runtime.d.ts +3 -2
  26. package/dist/content/runtime.js +43 -26
  27. package/dist/core/app/app.d.ts +0 -2
  28. package/dist/core/app/app.js +0 -7
  29. package/dist/core/app/base.d.ts +32 -20
  30. package/dist/core/app/base.js +79 -73
  31. package/dist/core/app/dev-facade.d.ts +27 -0
  32. package/dist/core/app/dev-facade.js +51 -0
  33. package/dist/core/app/entrypoints/index.d.ts +0 -1
  34. package/dist/core/app/entrypoints/index.js +0 -2
  35. package/dist/core/app/entrypoints/virtual/dev.js +24 -19
  36. package/dist/core/app/node.js +13 -14
  37. package/dist/core/app/prepare-response.d.ts +1 -1
  38. package/dist/core/app/validate-headers.js +7 -3
  39. package/dist/core/build/app.d.ts +31 -6
  40. package/dist/core/build/app.js +31 -13
  41. package/dist/core/build/environment.d.ts +25 -0
  42. package/dist/core/build/environment.js +157 -0
  43. package/dist/core/cache/handler.d.ts +13 -7
  44. package/dist/core/cache/handler.js +55 -51
  45. package/dist/core/cache/provider.d.ts +4 -0
  46. package/dist/core/cache/provider.js +15 -0
  47. package/dist/core/constants.d.ts +0 -11
  48. package/dist/core/constants.js +1 -5
  49. package/dist/core/dev/dev.js +1 -1
  50. package/dist/core/environment/dev-nonrunnable.d.ts +6 -0
  51. package/dist/core/environment/dev-nonrunnable.js +170 -0
  52. package/dist/core/environment/index.d.ts +90 -0
  53. package/dist/core/environment/index.js +12 -0
  54. package/dist/core/environment/production.d.ts +6 -0
  55. package/dist/core/environment/production.js +117 -0
  56. package/dist/core/errors/build-handler.d.ts +5 -10
  57. package/dist/core/errors/build-handler.js +11 -17
  58. package/dist/core/errors/default-handler.d.ts +4 -9
  59. package/dist/core/errors/default-handler.js +92 -107
  60. package/dist/core/errors/dev-handler.d.ts +7 -11
  61. package/dist/core/errors/dev-handler.js +71 -69
  62. package/dist/core/errors/errors-data.d.ts +18 -0
  63. package/dist/core/errors/errors-data.js +7 -0
  64. package/dist/core/errors/handler.d.ts +22 -3
  65. package/dist/core/errors/handler.js +25 -0
  66. package/dist/core/fetch/default-handler.d.ts +15 -8
  67. package/dist/core/fetch/default-handler.js +12 -34
  68. package/dist/core/fetch/features.d.ts +23 -0
  69. package/dist/core/fetch/features.js +27 -0
  70. package/dist/core/fetch/fetch-state.d.ts +52 -7
  71. package/dist/core/fetch/fetch-state.js +99 -92
  72. package/dist/core/fetch/index.d.ts +9 -2
  73. package/dist/core/fetch/index.js +18 -79
  74. package/dist/core/fetch/vite-plugin.js +2 -1
  75. package/dist/core/i18n/domain.js +4 -11
  76. package/dist/core/i18n/handler.d.ts +28 -13
  77. package/dist/core/i18n/handler.js +100 -100
  78. package/dist/core/logger/manifest-logger.d.ts +31 -0
  79. package/dist/core/logger/manifest-logger.js +37 -0
  80. package/dist/core/manifest/ambient-source.d.ts +2 -0
  81. package/dist/core/manifest/ambient-source.js +4 -0
  82. package/dist/core/manifest/ambient.d.ts +16 -0
  83. package/dist/core/manifest/ambient.js +22 -0
  84. package/dist/core/manifest/derived.d.ts +3 -0
  85. package/dist/core/manifest/derived.js +10 -0
  86. package/dist/core/manifest/memo.d.ts +31 -0
  87. package/dist/core/manifest/memo.js +47 -0
  88. package/dist/core/messages/runtime.js +1 -1
  89. package/dist/core/middleware/astro-middleware.d.ts +25 -35
  90. package/dist/core/middleware/astro-middleware.js +61 -81
  91. package/dist/core/middleware/load.d.ts +19 -0
  92. package/dist/core/middleware/load.js +36 -0
  93. package/dist/core/middleware/sequence.js +15 -7
  94. package/dist/core/pages/handler.d.ts +18 -25
  95. package/dist/core/pages/handler.js +68 -84
  96. package/dist/core/redirects/render.js +3 -8
  97. package/dist/core/render/index.d.ts +0 -1
  98. package/dist/core/render/index.js +0 -2
  99. package/dist/core/render/route-cache.d.ts +6 -1
  100. package/dist/core/render/route-cache.js +11 -1
  101. package/dist/core/rewrites/handler.d.ts +4 -6
  102. package/dist/core/rewrites/handler.js +19 -20
  103. package/dist/core/routing/default.d.ts +2 -0
  104. package/dist/core/routing/default.js +7 -1
  105. package/dist/core/routing/dev.d.ts +1 -3
  106. package/dist/core/routing/dev.js +12 -5
  107. package/dist/core/routing/handler.d.ts +6 -16
  108. package/dist/core/routing/handler.js +126 -164
  109. package/dist/core/routing/helpers.d.ts +7 -1
  110. package/dist/core/routing/helpers.js +21 -0
  111. package/dist/core/routing/match-request.d.ts +10 -0
  112. package/dist/core/routing/match-request.js +46 -0
  113. package/dist/core/routing/route-table.d.ts +34 -0
  114. package/dist/core/routing/route-table.js +41 -0
  115. package/dist/core/routing/trailing-slash-handler.d.ts +4 -14
  116. package/dist/core/routing/trailing-slash-handler.js +39 -50
  117. package/dist/core/server-islands/mappings.d.ts +6 -0
  118. package/dist/core/server-islands/mappings.js +12 -0
  119. package/dist/core/session/driver.d.ts +4 -0
  120. package/dist/core/session/driver.js +14 -0
  121. package/dist/core/session/handler.d.ts +1 -1
  122. package/dist/core/session/handler.js +8 -8
  123. package/dist/core/session/provider-disabled.js +2 -2
  124. package/dist/entrypoints/prerender.js +5 -1
  125. package/dist/i18n/middleware.d.ts +4 -4
  126. package/dist/i18n/middleware.js +3 -3
  127. package/dist/manifest/serialized.d.ts +1 -0
  128. package/dist/manifest/serialized.js +9 -2
  129. package/dist/runtime/prerender/static-paths.d.ts +14 -2
  130. package/dist/runtime/prerender/static-paths.js +4 -3
  131. package/dist/types/public/config.d.ts +433 -241
  132. package/dist/vite-plugin-app/createAstroServerApp.js +22 -18
  133. package/dist/vite-plugin-app/environment.d.ts +18 -0
  134. package/dist/vite-plugin-app/environment.js +210 -0
  135. package/dist/vite-plugin-app/handle-request.d.ts +30 -0
  136. package/dist/vite-plugin-app/handle-request.js +129 -0
  137. package/dist/vite-plugin-app/index.d.ts +1 -1
  138. package/dist/vite-plugin-app/index.js +1 -1
  139. package/package.json +14 -7
  140. package/src/core/README.md +37 -0
  141. package/src/core/manifest/ambient-source.ts +9 -0
  142. package/src/types/README.md +5 -0
  143. package/dist/container/pipeline.d.ts +0 -14
  144. package/dist/container/pipeline.js +0 -78
  145. package/dist/core/app/dev/app.d.ts +0 -31
  146. package/dist/core/app/dev/app.js +0 -80
  147. package/dist/core/app/dev/pipeline.d.ts +0 -17
  148. package/dist/core/app/dev/pipeline.js +0 -133
  149. package/dist/core/app/pipeline.d.ts +0 -14
  150. package/dist/core/app/pipeline.js +0 -123
  151. package/dist/core/base-pipeline.d.ts +0 -183
  152. package/dist/core/base-pipeline.js +0 -293
  153. package/dist/core/build/pipeline.d.ts +0 -38
  154. package/dist/core/build/pipeline.js +0 -202
  155. package/dist/vite-plugin-app/app.d.ts +0 -62
  156. package/dist/vite-plugin-app/app.js +0 -237
  157. package/dist/vite-plugin-app/pipeline.d.ts +0 -25
  158. package/dist/vite-plugin-app/pipeline.js +0 -189
@@ -18,8 +18,8 @@ interface TryRewriteResult {
18
18
  * - Invalidates cached API contexts so they're re-derived from the
19
19
  * new route.
20
20
  *
21
- * Called by both `Rewrites.execute()` (user-triggered `Astro.rewrite`)
22
- * and `AstroMiddleware` (middleware `next(payload)`).
21
+ * Called by both `executeRewrite()` (user-triggered `Astro.rewrite`)
22
+ * and `handleMiddleware` (middleware `next(payload)`).
23
23
  */
24
24
  export declare function applyRewriteToState(state: FetchState, payload: RewritePayload, { routeData, componentInstance, newUrl, pathname }: TryRewriteResult, { mergeCookies }?: {
25
25
  mergeCookies?: boolean;
@@ -27,11 +27,9 @@ export declare function applyRewriteToState(state: FetchState, payload: RewriteP
27
27
  /**
28
28
  * Executes a user-triggered rewrite (`Astro.rewrite(...)` /
29
29
  * `ctx.rewrite(...)`) against a `FetchState`. Resolves the rewrite
30
- * target via `pipeline.tryRewrite`, validates it, mutates the
30
+ * target via the environment's `tryRewrite`, validates it, mutates the
31
31
  * `FetchState` to reflect the new route, and re-runs the middleware
32
32
  * and page dispatch to produce the new response.
33
33
  */
34
- export declare class Rewrites {
35
- execute(state: FetchState, payload: RewritePayload): Promise<Response>;
36
- }
34
+ export declare function executeRewrite(state: FetchState, payload: RewritePayload): Promise<Response>;
37
35
  export {};
@@ -1,16 +1,16 @@
1
1
  import { AstroCookies } from "../cookies/index.js";
2
+ import { getEnvironment } from "../environment/index.js";
2
3
  import { ForbiddenRewrite } from "../errors/errors-data.js";
3
4
  import { AstroError } from "../errors/errors.js";
4
- import { AstroMiddleware } from "../middleware/astro-middleware.js";
5
- import { PagesHandler } from "../pages/handler.js";
6
- import { getParams } from "../render/index.js";
5
+ import { handleMiddleware } from "../middleware/astro-middleware.js";
6
+ import { handlePages } from "../pages/handler.js";
7
+ import { getParams } from "../render/params-and-props.js";
7
8
  import { copyRequest, setOriginPathname } from "../routing/rewrite.js";
8
9
  import { createNormalizedUrl } from "../util/normalized-url.js";
9
10
  function applyRewriteToState(state, payload, { routeData, componentInstance, newUrl, pathname }, { mergeCookies = false } = {}) {
10
- const pipeline = state.pipeline;
11
11
  const oldPathname = state.pathname;
12
12
  const isI18nFallback = routeData.fallbackRoutes && routeData.fallbackRoutes.length > 0;
13
- if (pipeline.manifest.serverLike && !state.routeData.prerender && routeData.prerender && !isI18nFallback) {
13
+ if (state.manifest.serverLike && !state.routeData.prerender && routeData.prerender && !isI18nFallback) {
14
14
  throw new AstroError({
15
15
  ...ForbiddenRewrite,
16
16
  message: ForbiddenRewrite.message(state.pathname, pathname, routeData.component),
@@ -26,7 +26,7 @@ function applyRewriteToState(state, payload, { routeData, componentInstance, new
26
26
  newUrl,
27
27
  state.request,
28
28
  routeData.prerender,
29
- pipeline.logger,
29
+ state.logger,
30
30
  state.routeData.route
31
31
  );
32
32
  }
@@ -45,23 +45,22 @@ function applyRewriteToState(state, payload, { routeData, componentInstance, new
45
45
  setOriginPathname(
46
46
  state.request,
47
47
  oldPathname,
48
- pipeline.manifest.trailingSlash,
49
- pipeline.manifest.buildFormat
48
+ state.manifest.trailingSlash,
49
+ state.manifest.buildFormat
50
50
  );
51
51
  state.invalidateContexts();
52
52
  }
53
- class Rewrites {
54
- async execute(state, payload) {
55
- const pipeline = state.pipeline;
56
- pipeline.logger.debug("router", "Calling rewrite: ", payload);
57
- const result = await pipeline.tryRewrite(payload, state.request);
58
- applyRewriteToState(state, payload, result, { mergeCookies: true });
59
- const middleware = new AstroMiddleware(pipeline);
60
- const pagesHandler = new PagesHandler(pipeline);
61
- return middleware.handle(state, pagesHandler.handle.bind(pagesHandler));
62
- }
53
+ async function executeRewrite(state, payload) {
54
+ state.logger.debug("router", "Calling rewrite: ", payload);
55
+ const result = await getEnvironment(state.manifest).tryRewrite(
56
+ state.manifest,
57
+ payload,
58
+ state.request
59
+ );
60
+ applyRewriteToState(state, payload, result, { mergeCookies: true });
61
+ return handleMiddleware(state, handlePages);
63
62
  }
64
63
  export {
65
- Rewrites,
66
- applyRewriteToState
64
+ applyRewriteToState,
65
+ executeRewrite
67
66
  };
@@ -8,3 +8,5 @@ export interface DefaultRouteParams {
8
8
  }
9
9
  export declare const DEFAULT_COMPONENTS: string[];
10
10
  export declare function createDefaultRoutes(manifest: SSRManifest): DefaultRouteParams[];
11
+ /** The built-in internal routes for a manifest, derived once per manifest. */
12
+ export declare function getDefaultRoutes(manifest: SSRManifest): DefaultRouteParams[];
@@ -1,4 +1,5 @@
1
1
  import { DEFAULT_404_COMPONENT } from "../constants.js";
2
+ import { createManifestMemo } from "../manifest/memo.js";
2
3
  import {
3
4
  createEndpoint as createServerIslandEndpoint,
4
5
  SERVER_ISLAND_COMPONENT,
@@ -23,7 +24,12 @@ function createDefaultRoutes(manifest) {
23
24
  }
24
25
  ];
25
26
  }
27
+ const defaultRoutesMemo = createManifestMemo(createDefaultRoutes);
28
+ function getDefaultRoutes(manifest) {
29
+ return defaultRoutesMemo.get(manifest);
30
+ }
26
31
  export {
27
32
  DEFAULT_COMPONENTS,
28
- createDefaultRoutes
33
+ createDefaultRoutes,
34
+ getDefaultRoutes
29
35
  };
@@ -1,16 +1,14 @@
1
1
  /**
2
2
  * Use this module only to have functions needed in development
3
3
  */
4
- import type { RoutesList } from '../../types/astro.js';
5
4
  import type { SSRManifest } from '../app/types.js';
6
5
  import type { RouteData } from '../../types/public/index.js';
7
- import type { RunnablePipeline } from '../../vite-plugin-app/pipeline.js';
8
6
  interface MatchedRoute {
9
7
  route: RouteData;
10
8
  filePath: URL;
11
9
  resolvedPathname: string;
12
10
  }
13
- export declare function matchRoute(pathname: string, routesList: RoutesList, pipeline: RunnablePipeline, manifest: SSRManifest, { prerenderOnly }?: {
11
+ export declare function matchRoute(manifest: SSRManifest, pathname: string, { prerenderOnly }?: {
14
12
  prerenderOnly?: boolean;
15
13
  }): Promise<MatchedRoute | undefined>;
16
14
  export {};
@@ -4,9 +4,16 @@ import { getProps } from "../render/index.js";
4
4
  import { getCustom404Route } from "./helpers.js";
5
5
  import { NoMatchingStaticPathFound } from "../errors/errors-data.js";
6
6
  import { isAstroError } from "../errors/errors.js";
7
+ import { getEnvironment } from "../environment/index.js";
8
+ import { getLogger } from "../logger/manifest-logger.js";
9
+ import { getRouteCache } from "../render/route-cache.js";
10
+ import { getRouteTable } from "./route-table.js";
7
11
  import { getErrorRoutePath } from "../../i18n/error-routes.js";
8
- async function matchRoute(pathname, routesList, pipeline, manifest, { prerenderOnly } = {}) {
9
- const { logger, routeCache } = pipeline;
12
+ async function matchRoute(manifest, pathname, { prerenderOnly } = {}) {
13
+ const logger = getLogger(manifest);
14
+ const routeCache = getRouteCache(manifest);
15
+ const env = getEnvironment(manifest);
16
+ const routesList = getRouteTable(manifest);
10
17
  const matches = matchAllRoutes(pathname, routesList);
11
18
  const preloadedMatches = getSortedPreloadedMatches({
12
19
  matches,
@@ -21,12 +28,12 @@ async function matchRoute(pathname, routesList, pipeline, manifest, { prerenderO
21
28
  }
22
29
  try {
23
30
  await getProps({
24
- mod: await pipeline.getComponentByRoute(maybeRoute),
31
+ mod: await env.getComponentByRoute(manifest, maybeRoute),
25
32
  routeData: maybeRoute,
26
33
  routeCache,
27
34
  pathname,
28
35
  logger,
29
- serverLike: pipeline.manifest.serverLike,
36
+ serverLike: manifest.serverLike,
30
37
  base: manifest.base,
31
38
  trailingSlash: manifest.trailingSlash
32
39
  });
@@ -48,7 +55,7 @@ async function matchRoute(pathname, routesList, pipeline, manifest, { prerenderO
48
55
  }
49
56
  const altPathname = pathname.replace(/\/index\.html$/, "/").replace(/\.html$/, "");
50
57
  if (altPathname !== pathname) {
51
- return await matchRoute(altPathname, routesList, pipeline, manifest, { prerenderOnly });
58
+ return await matchRoute(manifest, altPathname, { prerenderOnly });
52
59
  }
53
60
  if (skippedPrerenderOnly) {
54
61
  return void 0;
@@ -1,17 +1,7 @@
1
1
  import type { FetchState } from '../fetch/fetch-state.js';
2
- import type { BaseApp } from '../app/base.js';
3
- import { type Pipeline } from '../base-pipeline.js';
4
- export declare class AstroHandler {
5
- #private;
6
- constructor(app: BaseApp<Pipeline>);
7
- handle(state: FetchState): Promise<Response>;
8
- /**
9
- * Renders a response for the given `FetchState`. Assumes
10
- * trailing-slash redirects and routeData resolution have already run.
11
- *
12
- * User-triggered rewrites (`Astro.rewrite` / `ctx.rewrite`) go through
13
- * `Rewrites.execute` on the current `FetchState` — they mutate the
14
- * existing state in place and re-run middleware + page dispatch.
15
- */
16
- render(state: FetchState): Promise<Response>;
17
- }
2
+ /**
3
+ * The composite "batteries-included" handler that wires up every request
4
+ * feature internally; `astro(state)` (astro/fetch) delegates here, as does
5
+ * `BaseApp.render`'s default-handler fast path.
6
+ */
7
+ export declare function handleRequest(state: FetchState): Promise<Response>;
@@ -1,183 +1,145 @@
1
- import { ActionHandler } from "../../actions/handler.js";
1
+ import { handleAction } from "../../actions/handler.js";
2
2
  import { REROUTABLE_STATUS_CODES } from "../constants.js";
3
- import { TrailingSlashHandler } from "./trailing-slash-handler.js";
4
- import { CacheHandler, provideCache } from "../cache/handler.js";
5
- import { I18n } from "../i18n/handler.js";
6
- import { AstroMiddleware } from "../middleware/astro-middleware.js";
7
- import { PagesHandler } from "../pages/handler.js";
3
+ import { handleTrailingSlash } from "./trailing-slash-handler.js";
4
+ import { handleCache, provideCache } from "../cache/handler.js";
5
+ import { getEnvironment } from "../environment/index.js";
6
+ import { renderErrorFromState } from "../errors/handler.js";
7
+ import { ALL_FETCH_FEATURES, markFeatureUsed, FetchFeatures } from "../fetch/features.js";
8
+ import { finalizeI18n, getI18n } from "../i18n/handler.js";
9
+ import { getResolvedLogger } from "../logger/manifest-logger.js";
10
+ import { handleMiddleware } from "../middleware/astro-middleware.js";
11
+ import { handlePages } from "../pages/handler.js";
8
12
  import { renderRedirect } from "../redirects/render.js";
9
13
  import { provideSession } from "../session/provider.js";
10
14
  import { prepareResponse } from "../app/prepare-response.js";
11
- import { ALL_PIPELINE_FEATURES, PipelineFeatures } from "../base-pipeline.js";
12
- class AstroHandler {
13
- #app;
14
- #trailingSlashHandler;
15
- #actionHandler;
16
- #astroMiddleware;
17
- #pagesHandler;
18
- #cacheHandler;
19
- /** Bound callback for the middleware chain — created once, reused per request. */
20
- #renderRouteCallback;
21
- /**
22
- * i18n post-processor. Only set when the app has i18n configured and
23
- * the strategy is not `manual` — for the manual strategy users wire
24
- * `astro:i18n.middleware(...)` into their own `onRequest`.
25
- */
26
- #i18n;
27
- /** Whether sessions are configured on the manifest. */
28
- #hasSession;
29
- constructor(app) {
30
- this.#app = app;
31
- this.#trailingSlashHandler = new TrailingSlashHandler(app);
32
- this.#actionHandler = new ActionHandler();
33
- this.#astroMiddleware = new AstroMiddleware(app.pipeline);
34
- this.#pagesHandler = new PagesHandler(app.pipeline);
35
- this.#cacheHandler = new CacheHandler(app);
36
- this.#renderRouteCallback = this.#actionsAndPages.bind(this);
37
- this.#hasSession = !!app.manifest.sessionConfig;
38
- const i18n = app.manifest.i18n;
39
- if (i18n && i18n.strategy !== "manual") {
40
- this.#i18n = new I18n(
41
- i18n,
42
- app.manifest.base,
43
- app.manifest.trailingSlash,
44
- app.manifest.buildFormat
45
- );
46
- }
15
+ import { getDefaultStatusCode } from "./helpers.js";
16
+ function logRequestFromState(state, payload) {
17
+ if (state.logRequest) {
18
+ state.logRequest(payload);
19
+ } else {
20
+ getEnvironment(state.manifest).logRequest(state.manifest, payload);
47
21
  }
48
- /**
49
- * Runs actions then pages — the callback at the bottom of the
50
- * middleware chain. Bound once in the constructor to avoid
51
- * per-request closure allocation.
52
- */
53
- #actionsAndPages(state, ctx) {
54
- if (!state.skipMiddleware) {
55
- const actionResult = this.#actionHandler.handle(ctx, state);
56
- if (actionResult) {
57
- return actionResult.then((response) => response ?? this.#pagesHandler.handle(state, ctx));
58
- }
22
+ }
23
+ function actionsAndPages(state, ctx) {
24
+ if (!state.skipMiddleware) {
25
+ const actionResult = handleAction(ctx, state);
26
+ if (actionResult) {
27
+ return actionResult.then((response) => response ?? handlePages(state, ctx));
59
28
  }
60
- return this.#pagesHandler.handle(state, ctx);
61
29
  }
62
- async handle(state) {
63
- state.pipeline.usedFeatures |= ALL_PIPELINE_FEATURES;
64
- if (state.invalidEncoding) {
65
- return new Response(null, { status: 400, statusText: "Bad Request" });
66
- }
67
- const trailingSlashRedirect = this.#trailingSlashHandler.handle(state);
68
- if (trailingSlashRedirect) {
69
- return trailingSlashRedirect;
70
- }
71
- if (!state.routeData) {
72
- return this.#app.renderError(state.request, {
73
- ...state.renderOptions,
74
- status: 404,
75
- pathname: state.pathname
76
- });
77
- }
78
- return this.render(state);
30
+ return handlePages(state, ctx);
31
+ }
32
+ async function handleRequest(state) {
33
+ await getResolvedLogger(state.manifest);
34
+ markFeatureUsed(state.manifest, ALL_FETCH_FEATURES);
35
+ if (state.invalidEncoding) {
36
+ return new Response(null, { status: 400, statusText: "Bad Request" });
79
37
  }
80
- /**
81
- * Renders a response for the given `FetchState`. Assumes
82
- * trailing-slash redirects and routeData resolution have already run.
83
- *
84
- * User-triggered rewrites (`Astro.rewrite` / `ctx.rewrite`) go through
85
- * `Rewrites.execute` on the current `FetchState` — they mutate the
86
- * existing state in place and re-run middleware + page dispatch.
87
- */
88
- async render(state) {
89
- const routeData = state.routeData;
90
- const pathname = state.pathname;
91
- const request = state.request;
92
- const { addCookieHeader } = state.renderOptions;
93
- const defaultStatus = this.#app.getDefaultStatusCode(routeData, pathname);
94
- state.status = defaultStatus;
95
- let response;
96
- let finalizeError;
97
- try {
98
- const sessionP = this.#hasSession ? provideSession(state) : void 0;
99
- const cacheP = provideCache(state);
100
- if (sessionP || cacheP) await Promise.all([sessionP, cacheP]);
101
- state.pipeline.usedFeatures |= PipelineFeatures.sessions;
102
- if (routeData.type === "redirect") {
103
- const redirectResponse = await renderRedirect(state);
104
- this.#app.logThisRequest({
105
- pathname,
106
- method: request.method,
107
- statusCode: redirectResponse.status,
108
- isRewrite: false,
109
- timeStart: state.timeStart
110
- });
111
- prepareResponse(redirectResponse, { addCookieHeader });
112
- this.#app.pipeline.logger.flush();
113
- return redirectResponse;
114
- }
115
- if (!this.#app.pipeline.cacheProvider) {
116
- this.#app.pipeline.usedFeatures |= PipelineFeatures.cache;
117
- response = await this.#astroMiddleware.handle(state, this.#renderRouteCallback);
118
- if (this.#i18n) {
119
- response = await this.#i18n.finalize(state, response);
120
- }
121
- } else {
122
- const runPipeline = async () => {
123
- let res = await this.#astroMiddleware.handle(state, this.#renderRouteCallback);
124
- if (this.#i18n) {
125
- res = await this.#i18n.finalize(state, res);
126
- }
127
- return res;
128
- };
129
- response = await this.#cacheHandler.handle(state, runPipeline);
130
- }
131
- this.#app.logThisRequest({
38
+ const trailingSlashRedirect = handleTrailingSlash(state);
39
+ if (trailingSlashRedirect) {
40
+ return trailingSlashRedirect;
41
+ }
42
+ if (!state.routeData) {
43
+ return renderErrorFromState(state, state.request, {
44
+ ...state.renderOptions,
45
+ status: 404,
46
+ pathname: state.pathname
47
+ });
48
+ }
49
+ return render(state);
50
+ }
51
+ async function render(state) {
52
+ const routeData = state.routeData;
53
+ const pathname = state.pathname;
54
+ const request = state.request;
55
+ const { addCookieHeader } = state.renderOptions;
56
+ state.status = getDefaultStatusCode(state.manifest, routeData, pathname);
57
+ let response;
58
+ let finalizeError;
59
+ try {
60
+ const sessionP = state.manifest.sessionConfig ? provideSession(state) : void 0;
61
+ const cacheP = provideCache(state);
62
+ if (sessionP || cacheP) await Promise.all([sessionP, cacheP]);
63
+ markFeatureUsed(state.manifest, FetchFeatures.sessions);
64
+ if (routeData.type === "redirect") {
65
+ const redirectResponse = await renderRedirect(state);
66
+ logRequestFromState(state, {
132
67
  pathname,
133
68
  method: request.method,
134
- statusCode: response.status,
135
- isRewrite: state.isRewriting,
69
+ statusCode: redirectResponse.status,
70
+ isRewrite: false,
136
71
  timeStart: state.timeStart
137
72
  });
138
- } catch (err) {
139
- this.#app.logger.error(null, err.stack || err.message || String(err));
140
- return this.#app.renderError(request, {
141
- ...state.renderOptions,
142
- status: 500,
143
- error: err,
144
- pathname: state.pathname
145
- });
146
- } finally {
147
- try {
148
- const finalize = state.finalizeAll();
149
- if (finalize) await finalize;
150
- } catch (err) {
151
- finalizeError = err;
152
- this.#app.logger.error(null, err.stack || err.message || String(err));
153
- }
73
+ prepareResponse(redirectResponse, { addCookieHeader });
74
+ state.logger.flush();
75
+ return redirectResponse;
154
76
  }
155
- if (finalizeError) {
156
- return this.#app.renderError(request, {
157
- ...state.renderOptions,
158
- status: 500,
159
- error: finalizeError,
160
- pathname: state.pathname
161
- });
77
+ const i18n = getI18n(state.manifest);
78
+ if (!state.manifest.cacheProvider) {
79
+ markFeatureUsed(state.manifest, FetchFeatures.cache);
80
+ response = await handleMiddleware(state, actionsAndPages);
81
+ if (i18n) {
82
+ response = await finalizeI18n(i18n, state, response);
83
+ }
84
+ } else {
85
+ const runPipeline = async () => {
86
+ let res = await handleMiddleware(state, actionsAndPages);
87
+ if (i18n) {
88
+ res = await finalizeI18n(i18n, state, res);
89
+ }
90
+ return res;
91
+ };
92
+ response = await handleCache(state, runPipeline);
162
93
  }
163
- if (REROUTABLE_STATUS_CODES.includes(response.status) && // If the body isn't null, that means the user sets the 404 status
164
- // but uses the current route to handle the 404
165
- response.body === null && !state.skipErrorReroute) {
166
- return this.#app.renderError(request, {
167
- ...state.renderOptions,
168
- response,
169
- status: response.status,
170
- // We don't have an error to report here. Passing null means we pass nothing intentionally
171
- // while undefined means there's no error
172
- error: response.status === 500 ? null : void 0,
173
- pathname: state.pathname
174
- });
94
+ logRequestFromState(state, {
95
+ pathname,
96
+ method: request.method,
97
+ statusCode: response.status,
98
+ isRewrite: state.isRewriting,
99
+ timeStart: state.timeStart
100
+ });
101
+ } catch (err) {
102
+ state.logger.error(null, err.stack || err.message || String(err));
103
+ return renderErrorFromState(state, request, {
104
+ ...state.renderOptions,
105
+ status: 500,
106
+ error: err,
107
+ pathname: state.pathname
108
+ });
109
+ } finally {
110
+ try {
111
+ const finalize = state.finalizeAll();
112
+ if (finalize) await finalize;
113
+ } catch (err) {
114
+ finalizeError = err;
115
+ state.logger.error(null, err.stack || err.message || String(err));
175
116
  }
176
- prepareResponse(response, { addCookieHeader });
177
- this.#app.pipeline.logger.flush();
178
- return response;
179
117
  }
118
+ if (finalizeError) {
119
+ return renderErrorFromState(state, request, {
120
+ ...state.renderOptions,
121
+ status: 500,
122
+ error: finalizeError,
123
+ pathname: state.pathname
124
+ });
125
+ }
126
+ if (REROUTABLE_STATUS_CODES.includes(response.status) && // If the body isn't null, that means the user sets the 404 status
127
+ // but uses the current route to handle the 404
128
+ response.body === null && !state.skipErrorReroute) {
129
+ return renderErrorFromState(state, request, {
130
+ ...state.renderOptions,
131
+ response,
132
+ status: response.status,
133
+ // We don't have an error to report here. Passing null means we pass nothing intentionally
134
+ // while undefined means there's no error
135
+ error: response.status === 500 ? null : void 0,
136
+ pathname: state.pathname
137
+ });
138
+ }
139
+ prepareResponse(response, { addCookieHeader });
140
+ state.logger.flush();
141
+ return response;
180
142
  }
181
143
  export {
182
- AstroHandler
144
+ handleRequest
183
145
  };
@@ -1,6 +1,6 @@
1
1
  import type { RouteData } from '../../types/public/internal.js';
2
2
  import type { IntegrationResolvedRoute } from '../../types/public/integrations.js';
3
- import type { RouteInfo } from '../app/types.js';
3
+ import type { RouteInfo, SSRManifest } from '../app/types.js';
4
4
  import type { RoutesList } from '../../types/astro.js';
5
5
  type RedirectRouteData = RouteData & {
6
6
  redirect: string;
@@ -32,6 +32,12 @@ export declare function getCustom404Route(manifestData: RoutesList): RouteData |
32
32
  * Return a user-provided 500 route if one exists.
33
33
  */
34
34
  export declare function getCustom500Route(manifestData: RoutesList): RouteData | undefined;
35
+ /**
36
+ * Computes the default HTTP status code a route renders with:
37
+ * `302` for i18n fallback matches, `404`/`500` for (possibly localized)
38
+ * error routes, `200` otherwise.
39
+ */
40
+ export declare function getDefaultStatusCode(manifest: SSRManifest, routeData: RouteData, pathname: string): number;
35
41
  /**
36
42
  * Returns true if the route definition contains `.html` as a static segment part,
37
43
  * as is the case for routes like `[slug].html.astro`. Used to avoid stripping the
@@ -1,3 +1,5 @@
1
+ import { removeTrailingForwardSlash } from "@astrojs/internal-helpers/path";
2
+ import { isLocalizedErrorRoute } from "../../i18n/error-routes.js";
1
3
  import { isRoute404, isRoute500 } from "./internal/route-errors.js";
2
4
  function routeIsRedirect(route) {
3
5
  return route?.type === "redirect";
@@ -25,6 +27,24 @@ function getCustom404Route(manifestData) {
25
27
  function getCustom500Route(manifestData) {
26
28
  return manifestData.routes.find((r) => isRoute500(r.route));
27
29
  }
30
+ function getDefaultStatusCode(manifest, routeData, pathname) {
31
+ if (!routeData.pattern.test(pathname)) {
32
+ for (const fallbackRoute of routeData.fallbackRoutes) {
33
+ if (fallbackRoute.pattern.test(pathname)) {
34
+ return 302;
35
+ }
36
+ }
37
+ }
38
+ const route = removeTrailingForwardSlash(routeData.route);
39
+ const locales = manifest.i18n?.locales;
40
+ if (isRoute404(route) || isLocalizedErrorRoute(route, 404, locales)) {
41
+ return 404;
42
+ }
43
+ if (isRoute500(route) || isLocalizedErrorRoute(route, 500, locales)) {
44
+ return 500;
45
+ }
46
+ return 200;
47
+ }
28
48
  function routeHasHtmlExtension(route) {
29
49
  return route.segments.some(
30
50
  (segment) => segment.some((part) => !part.dynamic && part.content.includes(".html"))
@@ -43,6 +63,7 @@ function hasNonPrerenderedRoute(routes, options) {
43
63
  export {
44
64
  getCustom404Route,
45
65
  getCustom500Route,
66
+ getDefaultStatusCode,
46
67
  getFallbackRoute,
47
68
  hasNonPrerenderedRoute,
48
69
  routeHasHtmlExtension,
@@ -0,0 +1,10 @@
1
+ import type { RouteData } from '../../types/public/internal.js';
2
+ import type { SSRManifest } from '../app/types.js';
3
+ /**
4
+ * Given a `Request`, returns the `RouteData` that matches its pathname — the
5
+ * appless, purely functional body of `BaseApp.match()`. By default, prerendered
6
+ * routes aren't returned, even if they are matched; when
7
+ * `allowPrerenderedRoutes` is `true`, matched prerendered routes are returned
8
+ * too.
9
+ */
10
+ export declare function matchRequest(manifest: SSRManifest, request: Request, allowPrerenderedRoutes?: boolean): RouteData | undefined;
@@ -0,0 +1,46 @@
1
+ import { prependForwardSlash, stripRequestBase } from "@astrojs/internal-helpers/path";
2
+ import { computePathnameFromDomain } from "../i18n/domain.js";
3
+ import { AstroIntegrationLogger } from "../logger/core.js";
4
+ import { getLogger } from "../logger/manifest-logger.js";
5
+ import { matchAllRoutes, matchRoute } from "./route-table.js";
6
+ function safeDecodeURI(manifest, pathname) {
7
+ try {
8
+ return decodeURI(pathname);
9
+ } catch (e) {
10
+ new AstroIntegrationLogger(getLogger(manifest).options, manifest.adapterName).debug(
11
+ e.toString()
12
+ );
13
+ return pathname;
14
+ }
15
+ }
16
+ function matchRequest(manifest, request, allowPrerenderedRoutes = false) {
17
+ const url = new URL(request.url);
18
+ if (manifest.assets.has(url.pathname)) return void 0;
19
+ let pathname = computePathnameFromDomain(
20
+ request,
21
+ url,
22
+ manifest.i18n,
23
+ manifest.base,
24
+ manifest.trailingSlash,
25
+ getLogger(manifest)
26
+ );
27
+ if (!pathname) {
28
+ pathname = prependForwardSlash(stripRequestBase(url.pathname, manifest.base));
29
+ }
30
+ const routeData = matchRoute(manifest, safeDecodeURI(manifest, pathname));
31
+ if (!routeData) return void 0;
32
+ if (allowPrerenderedRoutes) {
33
+ return routeData;
34
+ }
35
+ if (routeData.prerender) {
36
+ if (routeData.params.length > 0) {
37
+ const allMatches = matchAllRoutes(manifest, safeDecodeURI(manifest, pathname));
38
+ return allMatches.find((r) => !r.prerender);
39
+ }
40
+ return void 0;
41
+ }
42
+ return routeData;
43
+ }
44
+ export {
45
+ matchRequest
46
+ };