astro 7.0.0-beta.4 → 7.0.0-beta.6

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 (47) hide show
  1. package/dist/cli/infra/build-time-astro-version-provider.js +1 -1
  2. package/dist/content/content-layer.js +3 -3
  3. package/dist/core/app/prepare-response.d.ts +2 -3
  4. package/dist/core/app/prepare-response.js +1 -6
  5. package/dist/core/build/generate.js +1 -1
  6. package/dist/core/build/plugins/plugin-manifest.js +1 -4
  7. package/dist/core/build/vite-build-config.js +6 -0
  8. package/dist/core/cache/config.d.ts +7 -6
  9. package/dist/core/cache/runtime/noop.js +1 -1
  10. package/dist/core/cache/utils.d.ts +3 -3
  11. package/dist/core/cache/vite-plugin.js +1 -1
  12. package/dist/core/config/schemas/base.d.ts +13 -13
  13. package/dist/core/config/schemas/base.js +4 -4
  14. package/dist/core/config/schemas/relative.d.ts +36 -36
  15. package/dist/core/constants.d.ts +0 -41
  16. package/dist/core/constants.js +1 -18
  17. package/dist/core/dev/dev.js +1 -1
  18. package/dist/core/errors/default-handler.js +1 -0
  19. package/dist/core/errors/errors-data.js +2 -2
  20. package/dist/core/fetch/fetch-state.d.ts +11 -0
  21. package/dist/core/fetch/fetch-state.js +19 -1
  22. package/dist/core/fetch/index.d.ts +8 -3
  23. package/dist/core/fetch/index.js +2 -2
  24. package/dist/core/i18n/handler.js +7 -13
  25. package/dist/core/messages/runtime.js +1 -1
  26. package/dist/core/middleware/astro-middleware.d.ts +19 -0
  27. package/dist/core/middleware/astro-middleware.js +43 -0
  28. package/dist/core/middleware/noop-middleware.js +0 -2
  29. package/dist/core/pages/handler.d.ts +13 -0
  30. package/dist/core/pages/handler.js +35 -14
  31. package/dist/core/routing/handler.js +6 -8
  32. package/dist/core/routing/rewrite.js +2 -1
  33. package/dist/core/util/pathname.d.ts +17 -16
  34. package/dist/core/util/pathname.js +6 -2
  35. package/dist/i18n/index.js +5 -7
  36. package/dist/manifest/serialized.js +2 -5
  37. package/dist/runtime/server/endpoint.d.ts +2 -1
  38. package/dist/runtime/server/endpoint.js +4 -13
  39. package/dist/types/public/config.d.ts +85 -83
  40. package/dist/virtual-modules/container.d.ts +1 -1
  41. package/dist/vite-plugin-config-alias/index.d.ts +2 -2
  42. package/dist/vite-plugin-config-alias/index.js +66 -61
  43. package/dist/vite-plugin-head/index.js +5 -11
  44. package/package.json +6 -6
  45. package/templates/content/module.mjs +0 -1
  46. package/dist/core/head-propagation/hint.d.ts +0 -4
  47. package/dist/core/head-propagation/hint.js +0 -7
@@ -1,6 +1,6 @@
1
1
  class BuildTimeAstroVersionProvider {
2
2
  // Injected during the build through esbuild define
3
- version = "7.0.0-beta.4";
3
+ version = "7.0.0-beta.6";
4
4
  }
5
5
  export {
6
6
  BuildTimeAstroVersionProvider
@@ -197,7 +197,7 @@ ${contentConfig.error.message}`
197
197
  logger.info("Content config changed");
198
198
  shouldClear = true;
199
199
  }
200
- if (previousAstroVersion && previousAstroVersion !== "7.0.0-beta.4") {
200
+ if (previousAstroVersion && previousAstroVersion !== "7.0.0-beta.6") {
201
201
  logger.info("Astro version changed");
202
202
  shouldClear = true;
203
203
  }
@@ -205,8 +205,8 @@ ${contentConfig.error.message}`
205
205
  logger.info("Clearing content store");
206
206
  this.#store.clearAll();
207
207
  }
208
- if ("7.0.0-beta.4") {
209
- this.#store.metaStore().set("astro-version", "7.0.0-beta.4");
208
+ if ("7.0.0-beta.6") {
209
+ this.#store.metaStore().set("astro-version", "7.0.0-beta.6");
210
210
  }
211
211
  if (currentConfigDigest) {
212
212
  this.#store.metaStore().set("content-config-digest", currentConfigDigest);
@@ -1,7 +1,6 @@
1
1
  /**
2
- * Strips internal-only headers from the response before sending it to the
3
- * user agent, and optionally appends cookies written via `Astro.cookie.set()`
4
- * to the `Set-Cookie` header.
2
+ * Appends cookies written via `Astro.cookie.set()` to the `Set-Cookie` header
3
+ * and marks the response as sent.
5
4
  *
6
5
  * This is a pure function with no dependencies on the app; it is shared by
7
6
  * `AstroHandler` and the various error handlers.
@@ -1,11 +1,6 @@
1
- import { INTERNAL_RESPONSE_HEADERS, responseSentSymbol } from "../constants.js";
1
+ import { responseSentSymbol } from "../constants.js";
2
2
  import { getSetCookiesFromResponse } from "../cookies/index.js";
3
3
  function prepareResponse(response, { addCookieHeader }) {
4
- for (const headerName of INTERNAL_RESPONSE_HEADERS) {
5
- if (response.headers.has(headerName)) {
6
- response.headers.delete(headerName);
7
- }
8
- }
9
4
  if (addCookieHeader) {
10
5
  for (const setCookieHeaderValue of getSetCookiesFromResponse(response)) {
11
6
  response.headers.append("set-cookie", setCookieHeaderValue);
@@ -267,7 +267,7 @@ async function renderPath({
267
267
  relativeLocation: locationSite,
268
268
  from: fromPath
269
269
  });
270
- if (config.compressHTML === true) {
270
+ if (config.compressHTML) {
271
271
  body = body.replaceAll("\n", "");
272
272
  }
273
273
  if (route.type !== "redirect") {
@@ -258,10 +258,7 @@ async function buildManifest(opts, internals, staticFiles, encodedKey) {
258
258
  allowedDomains: settings.config.security?.allowedDomains,
259
259
  key: encodedKey,
260
260
  sessionConfig: sessionConfigToManifest(settings.config.session),
261
- cacheConfig: cacheConfigToManifest(
262
- settings.config.experimental?.cache,
263
- settings.config.experimental?.routeRules
264
- ),
261
+ cacheConfig: cacheConfigToManifest(settings.config.cache, settings.config.routeRules),
265
262
  csp,
266
263
  image: {
267
264
  objectFit: settings.config.image.objectFit,
@@ -35,6 +35,12 @@ function createViteBuildConfig(opts) {
35
35
  ...viteConfig.build?.rolldownOptions,
36
36
  // Setting as `exports-only` allows us to safely delete inputs that are only used during prerendering
37
37
  preserveEntrySignatures: "exports-only",
38
+ checks: {
39
+ ...viteConfig.build?.rolldownOptions?.checks,
40
+ // Disable Rolldown's built-in plugin timing warnings. These fire by default
41
+ // and produce noisy warnings about slow plugins during normal builds.
42
+ pluginTimings: false
43
+ },
38
44
  ...legacyAdapter && settings.buildOutput === "server" ? { input: LEGACY_SSR_ENTRY_VIRTUAL_MODULE } : {},
39
45
  output: {
40
46
  hoistTransitiveImports: false,
@@ -1,7 +1,7 @@
1
1
  import * as z from 'zod/v4';
2
2
  /**
3
- * Cache provider configuration (experimental.cache).
4
- * Provider only - routes are configured via experimental.routeRules.
3
+ * Cache provider configuration (`cache`).
4
+ * Provider only - routes are configured via `routeRules`.
5
5
  */
6
6
  export declare const CacheSchema: z.ZodObject<{
7
7
  provider: z.ZodOptional<z.ZodObject<{
@@ -11,14 +11,15 @@ export declare const CacheSchema: z.ZodObject<{
11
11
  }, z.core.$strip>>;
12
12
  }, z.core.$strip>;
13
13
  /**
14
- * Route rules configuration (experimental.routeRules).
15
- * Maps glob patterns to route rules.
14
+ * Route rules configuration (`routeRules`).
15
+ * Maps route patterns to route rules. Patterns use the same `[param]` and
16
+ * `[...rest]` syntax as file-based routing; glob wildcards (`*`) are not supported.
16
17
  *
17
18
  * Example:
18
19
  * ```ts
19
20
  * routeRules: {
20
- * '/api/*': { swr: 600 },
21
- * '/products/*': { maxAge: 3600, tags: ['products'] },
21
+ * '/api/[...path]': { swr: 600 },
22
+ * '/products/[...slug]': { maxAge: 3600, tags: ['products'] },
22
23
  * }
23
24
  * ```
24
25
  */
@@ -26,7 +26,7 @@ class DisabledAstroCache {
26
26
  hasWarned = true;
27
27
  this.#logger?.warn(
28
28
  "cache",
29
- "`cache.set()` was called but caching is not enabled. Configure a cache provider in your Astro config under `experimental.cache` to enable caching."
29
+ "`cache.set()` was called but caching is not enabled. Configure a cache provider in your Astro config under `cache` to enable caching."
30
30
  );
31
31
  }
32
32
  }
@@ -10,7 +10,7 @@ export declare function normalizeRouteRuleCacheOptions(rule: {
10
10
  tags?: string[];
11
11
  } | undefined): CacheOptions | undefined;
12
12
  /**
13
- * Extract cache routes from experimental.routeRules config.
13
+ * Extract cache routes from the `routeRules` config.
14
14
  */
15
- export declare function extractCacheRoutesFromRouteRules(routeRules: AstroConfig['experimental']['routeRules']): Record<string, CacheOptions> | undefined;
16
- export declare function cacheConfigToManifest(cacheConfig: AstroConfig['experimental']['cache'], routeRulesConfig: AstroConfig['experimental']['routeRules']): SSRManifestCache | undefined;
15
+ export declare function extractCacheRoutesFromRouteRules(routeRules: AstroConfig['routeRules']): Record<string, CacheOptions> | undefined;
16
+ export declare function cacheConfigToManifest(cacheConfig: AstroConfig['cache'], routeRulesConfig: AstroConfig['routeRules']): SSRManifestCache | undefined;
@@ -7,7 +7,7 @@ const RESOLVED_VIRTUAL_CACHE_PROVIDER_ID = "\0" + VIRTUAL_CACHE_PROVIDER_ID;
7
7
  function vitePluginCacheProvider({
8
8
  settings
9
9
  }) {
10
- const providerConfig = settings.config.experimental?.cache?.provider;
10
+ const providerConfig = settings.config.cache?.provider;
11
11
  if (!providerConfig) {
12
12
  return;
13
13
  }
@@ -49,7 +49,7 @@ export declare const ASTRO_CONFIG_DEFAULTS: {
49
49
  devToolbar: {
50
50
  enabled: true;
51
51
  };
52
- compressHTML: true;
52
+ compressHTML: "jsx";
53
53
  server: {
54
54
  host: false;
55
55
  port: number;
@@ -504,6 +504,18 @@ export declare const AstroConfigSchema: z.ZodObject<{
504
504
  unicodeRange: z.ZodOptional<z.ZodTuple<[z.ZodString], z.ZodString>>;
505
505
  options: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
506
506
  }, z.core.$strict>>>;
507
+ cache: z.ZodOptional<z.ZodObject<{
508
+ provider: z.ZodOptional<z.ZodObject<{
509
+ config: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
510
+ entrypoint: z.ZodUnion<readonly [z.ZodString, z.ZodCustom<URL, URL>]>;
511
+ name: z.ZodOptional<z.ZodString>;
512
+ }, z.core.$strip>>;
513
+ }, z.core.$strip>>;
514
+ routeRules: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
515
+ maxAge: z.ZodOptional<z.ZodNumber>;
516
+ swr: z.ZodOptional<z.ZodNumber>;
517
+ tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
518
+ }, z.core.$strip>>>;
507
519
  experimental: z.ZodPrefault<z.ZodObject<{
508
520
  clientPrerender: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
509
521
  contentIntellisense: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
@@ -512,18 +524,6 @@ export declare const AstroConfigSchema: z.ZodObject<{
512
524
  name: z.ZodString;
513
525
  optimize: z.ZodCustom<(contents: string) => string | Promise<string>, (contents: string) => string | Promise<string>>;
514
526
  }, z.core.$strip>>;
515
- cache: z.ZodOptional<z.ZodObject<{
516
- provider: z.ZodOptional<z.ZodObject<{
517
- config: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
518
- entrypoint: z.ZodUnion<readonly [z.ZodString, z.ZodCustom<URL, URL>]>;
519
- name: z.ZodOptional<z.ZodString>;
520
- }, z.core.$strip>>;
521
- }, z.core.$strip>>;
522
- routeRules: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
523
- maxAge: z.ZodOptional<z.ZodNumber>;
524
- swr: z.ZodOptional<z.ZodNumber>;
525
- tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
526
- }, z.core.$strip>>>;
527
527
  }, z.core.$strict>>;
528
528
  legacy: z.ZodPrefault<z.ZodObject<{
529
529
  collectionsBackwardsCompat: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
@@ -38,7 +38,7 @@ const ASTRO_CONFIG_DEFAULTS = {
38
38
  devToolbar: {
39
39
  enabled: true
40
40
  },
41
- compressHTML: true,
41
+ compressHTML: "jsx",
42
42
  server: {
43
43
  host: false,
44
44
  port: 4321,
@@ -327,13 +327,13 @@ const AstroConfigSchema = z.object({
327
327
  config: z.record(z.string(), z.any()).optional()
328
328
  }).optional(),
329
329
  fonts: z.array(FontFamilySchema).optional(),
330
+ cache: CacheSchema.optional(),
331
+ routeRules: RouteRulesSchema.optional(),
330
332
  experimental: z.strictObject({
331
333
  clientPrerender: z.boolean().optional().default(ASTRO_CONFIG_DEFAULTS.experimental.clientPrerender),
332
334
  contentIntellisense: z.boolean().optional().default(ASTRO_CONFIG_DEFAULTS.experimental.contentIntellisense),
333
335
  chromeDevtoolsWorkspace: z.boolean().optional().default(ASTRO_CONFIG_DEFAULTS.experimental.chromeDevtoolsWorkspace),
334
- svgOptimizer: SvgOptimizerSchema.optional(),
335
- cache: CacheSchema.optional(),
336
- routeRules: RouteRulesSchema.optional()
336
+ svgOptimizer: SvgOptimizerSchema.optional()
337
337
  }).prefault({}),
338
338
  legacy: z.object({
339
339
  collectionsBackwardsCompat: z.boolean().optional().default(false)
@@ -392,6 +392,18 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
392
392
  unicodeRange: z.ZodOptional<z.ZodTuple<[z.ZodString], z.ZodString>>;
393
393
  options: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
394
394
  }, z.core.$strict>>>;
395
+ cache: z.ZodOptional<z.ZodObject<{
396
+ provider: z.ZodOptional<z.ZodObject<{
397
+ config: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
398
+ entrypoint: z.ZodUnion<readonly [z.ZodString, z.ZodCustom<URL, URL>]>;
399
+ name: z.ZodOptional<z.ZodString>;
400
+ }, z.core.$strip>>;
401
+ }, z.core.$strip>>;
402
+ routeRules: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
403
+ maxAge: z.ZodOptional<z.ZodNumber>;
404
+ swr: z.ZodOptional<z.ZodNumber>;
405
+ tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
406
+ }, z.core.$strip>>>;
395
407
  experimental: z.ZodPrefault<z.ZodObject<{
396
408
  clientPrerender: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
397
409
  contentIntellisense: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
@@ -400,18 +412,6 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
400
412
  name: z.ZodString;
401
413
  optimize: z.ZodCustom<(contents: string) => string | Promise<string>, (contents: string) => string | Promise<string>>;
402
414
  }, z.core.$strip>>;
403
- cache: z.ZodOptional<z.ZodObject<{
404
- provider: z.ZodOptional<z.ZodObject<{
405
- config: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
406
- entrypoint: z.ZodUnion<readonly [z.ZodString, z.ZodCustom<URL, URL>]>;
407
- name: z.ZodOptional<z.ZodString>;
408
- }, z.core.$strip>>;
409
- }, z.core.$strip>>;
410
- routeRules: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
411
- maxAge: z.ZodOptional<z.ZodNumber>;
412
- swr: z.ZodOptional<z.ZodNumber>;
413
- tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
414
- }, z.core.$strip>>>;
415
415
  }, z.core.$strict>>;
416
416
  legacy: z.ZodPrefault<z.ZodObject<{
417
417
  collectionsBackwardsCompat: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
@@ -590,18 +590,6 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
590
590
  name: string;
591
591
  optimize: (contents: string) => string | Promise<string>;
592
592
  } | undefined;
593
- cache?: {
594
- provider?: {
595
- entrypoint: string | URL;
596
- config?: Record<string, any> | undefined;
597
- name?: string | undefined;
598
- } | undefined;
599
- } | undefined;
600
- routeRules?: Record<string, {
601
- maxAge?: number | undefined;
602
- swr?: number | undefined;
603
- tags?: string[] | undefined;
604
- }> | undefined;
605
593
  };
606
594
  legacy: {
607
595
  collectionsBackwardsCompat: boolean;
@@ -696,6 +684,18 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
696
684
  unicodeRange?: [string, ...string[]] | undefined;
697
685
  options?: Record<string, any> | undefined;
698
686
  }[] | undefined;
687
+ cache?: {
688
+ provider?: {
689
+ entrypoint: string | URL;
690
+ config?: Record<string, any> | undefined;
691
+ name?: string | undefined;
692
+ } | undefined;
693
+ } | undefined;
694
+ routeRules?: Record<string, {
695
+ maxAge?: number | undefined;
696
+ swr?: number | undefined;
697
+ tags?: string[] | undefined;
698
+ }> | undefined;
699
699
  }, {
700
700
  base: string;
701
701
  trailingSlash: "never" | "ignore" | "always";
@@ -840,18 +840,6 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
840
840
  name: string;
841
841
  optimize: (contents: string) => string | Promise<string>;
842
842
  } | undefined;
843
- cache?: {
844
- provider?: {
845
- entrypoint: string | URL;
846
- config?: Record<string, any> | undefined;
847
- name?: string | undefined;
848
- } | undefined;
849
- } | undefined;
850
- routeRules?: Record<string, {
851
- maxAge?: number | undefined;
852
- swr?: number | undefined;
853
- tags?: string[] | undefined;
854
- }> | undefined;
855
843
  };
856
844
  legacy: {
857
845
  collectionsBackwardsCompat: boolean;
@@ -946,4 +934,16 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
946
934
  unicodeRange?: [string, ...string[]] | undefined;
947
935
  options?: Record<string, any> | undefined;
948
936
  }[] | undefined;
937
+ cache?: {
938
+ provider?: {
939
+ entrypoint: string | URL;
940
+ config?: Record<string, any> | undefined;
941
+ name?: string | undefined;
942
+ } | undefined;
943
+ } | undefined;
944
+ routeRules?: Record<string, {
945
+ maxAge?: number | undefined;
946
+ swr?: number | undefined;
947
+ tags?: string[] | undefined;
948
+ }> | undefined;
949
949
  }>>;
@@ -1,46 +1,5 @@
1
1
  export declare const ASTRO_VERSION: string;
2
2
  export declare const ASTRO_GENERATOR: string;
3
- /**
4
- * The name for the header used to help rerouting behavior.
5
- * When set to "no", astro will NOT try to reroute an error response to the corresponding error page, which is the default behavior that can sometimes lead to loops.
6
- *
7
- * ```ts
8
- * const response = new Response("keep this content as-is", {
9
- * status: 404,
10
- * headers: {
11
- * // note that using a variable name as the key of an object needs to be wrapped in square brackets in javascript
12
- * // without them, the header name will be interpreted as "REROUTE_DIRECTIVE_HEADER" instead of "X-Astro-Reroute"
13
- * [REROUTE_DIRECTIVE_HEADER]: 'no',
14
- * }
15
- * })
16
- * ```
17
- * Alternatively...
18
- * ```ts
19
- * response.headers.set(REROUTE_DIRECTIVE_HEADER, 'no');
20
- * ```
21
- */
22
- export declare const REROUTE_DIRECTIVE_HEADER = "X-Astro-Reroute";
23
- /**
24
- * Header and value that are attached to a Response object when a **user rewrite** occurs.
25
- *
26
- * This metadata is used to determine the origin of a Response. If a rewrite has occurred, it should be prioritised over other logic.
27
- */
28
- export declare const REWRITE_DIRECTIVE_HEADER_KEY = "X-Astro-Rewrite";
29
- export declare const REWRITE_DIRECTIVE_HEADER_VALUE = "yes";
30
- /**
31
- * This header is set by the no-op Astro middleware.
32
- */
33
- export declare const NOOP_MIDDLEWARE_HEADER = "X-Astro-Noop";
34
- /**
35
- * The name for the header used to help i18n middleware, which only needs to act on "page" and "fallback" route types.
36
- */
37
- export declare const ROUTE_TYPE_HEADER = "X-Astro-Route-Type";
38
- /**
39
- * Internal headers that should be stripped from the response before
40
- * sending it to the user agent. Add new internal headers here so
41
- * `prepareResponse` removes them automatically.
42
- */
43
- export declare const INTERNAL_RESPONSE_HEADERS: readonly ["X-Astro-Reroute", "X-Astro-Rewrite", "X-Astro-Noop", "X-Astro-Route-Type"];
44
3
  /**
45
4
  * Set by internal handlers (e.g. PagesHandler) to signal that a
46
5
  * response should be replaced with the corresponding error page.
@@ -1,16 +1,5 @@
1
- const ASTRO_VERSION = "7.0.0-beta.4";
1
+ const ASTRO_VERSION = "7.0.0-beta.6";
2
2
  const ASTRO_GENERATOR = `Astro v${ASTRO_VERSION}`;
3
- const REROUTE_DIRECTIVE_HEADER = "X-Astro-Reroute";
4
- const REWRITE_DIRECTIVE_HEADER_KEY = "X-Astro-Rewrite";
5
- const REWRITE_DIRECTIVE_HEADER_VALUE = "yes";
6
- const NOOP_MIDDLEWARE_HEADER = "X-Astro-Noop";
7
- const ROUTE_TYPE_HEADER = "X-Astro-Route-Type";
8
- const INTERNAL_RESPONSE_HEADERS = [
9
- REROUTE_DIRECTIVE_HEADER,
10
- REWRITE_DIRECTIVE_HEADER_KEY,
11
- NOOP_MIDDLEWARE_HEADER,
12
- ROUTE_TYPE_HEADER
13
- ];
14
3
  const ASTRO_ERROR_HEADER = "X-Astro-Error";
15
4
  const DEFAULT_404_COMPONENT = "astro-default-404.astro";
16
5
  const REDIRECT_STATUS_CODES = [301, 302, 303, 307, 308, 300, 304];
@@ -57,15 +46,9 @@ export {
57
46
  ASTRO_VERSION,
58
47
  ASTRO_VITE_ENVIRONMENT_NAMES,
59
48
  DEFAULT_404_COMPONENT,
60
- INTERNAL_RESPONSE_HEADERS,
61
49
  MIDDLEWARE_PATH_SEGMENT_NAME,
62
- NOOP_MIDDLEWARE_HEADER,
63
50
  REDIRECT_STATUS_CODES,
64
51
  REROUTABLE_STATUS_CODES,
65
- REROUTE_DIRECTIVE_HEADER,
66
- REWRITE_DIRECTIVE_HEADER_KEY,
67
- REWRITE_DIRECTIVE_HEADER_VALUE,
68
- ROUTE_TYPE_HEADER,
69
52
  SUPPORTED_MARKDOWN_FILE_EXTENSIONS,
70
53
  appSymbol,
71
54
  clientAddressSymbol,
@@ -26,7 +26,7 @@ async function dev(inlineConfig) {
26
26
  await telemetry.record([]);
27
27
  const restart = await createContainerWithAutomaticRestart({ inlineConfig, fs });
28
28
  const logger = restart.container.logger;
29
- const currentVersion = "7.0.0-beta.4";
29
+ const currentVersion = "7.0.0-beta.6";
30
30
  const isPrerelease = currentVersion.includes("-");
31
31
  if (!isPrerelease) {
32
32
  try {
@@ -79,6 +79,7 @@ class DefaultErrorHandler {
79
79
  return this.renderError(request, {
80
80
  ...resolvedRenderOptions,
81
81
  status,
82
+ error,
82
83
  response: originalResponse,
83
84
  skipMiddleware: true,
84
85
  pathname: resolvedPathname
@@ -793,8 +793,8 @@ const CacheProviderNotFound = {
793
793
  const CacheNotEnabled = {
794
794
  name: "CacheNotEnabled",
795
795
  title: "Cache is not enabled.",
796
- message: "`Astro.cache` is not available because the cache feature is not enabled. To use caching, configure a cache provider in your Astro config under `experimental.cache`.",
797
- hint: 'Use an adapter that provides a default cache provider, or set one explicitly: `experimental: { cache: { provider: "..." } }`. See https://docs.astro.build/en/reference/experimental-flags/route-caching/.'
796
+ message: "`Astro.cache` is not available because the cache feature is not enabled. To use caching, configure a cache provider in your Astro config under `cache`.",
797
+ hint: 'Use an adapter that provides a default cache provider, or set one explicitly: `cache: { provider: "..." }`. See https://docs.astro.build/en/guides/caching/.'
798
798
  };
799
799
  const CacheQueryConfigConflict = {
800
800
  name: "CacheQueryConfigConflict",
@@ -108,6 +108,12 @@ export declare class FetchState implements AstroFetchState {
108
108
  status: number;
109
109
  /** Whether user middleware should be skipped for this request. */
110
110
  skipMiddleware: boolean;
111
+ /**
112
+ * Set to `true` when the request path was encoded too many times to fully
113
+ * decode (see {@link validateAndDecodePathname}). These requests are
114
+ * rejected with a `400` before middleware or routing run.
115
+ */
116
+ invalidEncoding: boolean;
111
117
  /** A flag that tells the render content if the rewriting was triggered. */
112
118
  isRewriting: boolean;
113
119
  /** A safety net in case of loops (rewrite counter). */
@@ -122,6 +128,10 @@ export declare class FetchState implements AstroFetchState {
122
128
  clientAddress: string | undefined;
123
129
  /** Whether this is a partial render (container API). */
124
130
  partial: boolean | undefined;
131
+ /** Internal metadata about the current response route type. */
132
+ responseRouteType: 'page' | 'fallback' | undefined;
133
+ /** Internal flag to prevent rerouting this response to an error page. */
134
+ skipErrorReroute: boolean;
125
135
  /** Whether to inject CSP meta tags. */
126
136
  shouldInjectCspMetaTags: boolean | undefined;
127
137
  /** Request-scoped locals object, shared with user middleware. */
@@ -227,4 +237,5 @@ export declare class FetchState implements AstroFetchState {
227
237
  * after an in-flight rewrite swaps the route / request / params.
228
238
  */
229
239
  invalidateContexts(): void;
240
+ resetResponseMetadata(): void;
230
241
  }
@@ -29,7 +29,7 @@ import { getParams, getProps } from "../render/index.js";
29
29
  import { Rewrites } from "../rewrites/handler.js";
30
30
  import { isRoute404or500, isRouteServerIsland } from "../routing/match.js";
31
31
  import { normalizeUrl } from "../util/normalized-url.js";
32
- import { validateAndDecodePathname } from "../util/pathname.js";
32
+ import { MultiLevelEncodingError, validateAndDecodePathname } from "../util/pathname.js";
33
33
  import { getOriginPathname, setOriginPathname } from "../routing/rewrite.js";
34
34
  import { computePathnameFromDomain } from "../i18n/domain.js";
35
35
  import { getCustom404Route, routeHasHtmlExtension } from "../routing/helpers.js";
@@ -88,6 +88,12 @@ class FetchState {
88
88
  status = 200;
89
89
  /** Whether user middleware should be skipped for this request. */
90
90
  skipMiddleware = false;
91
+ /**
92
+ * Set to `true` when the request path was encoded too many times to fully
93
+ * decode (see {@link validateAndDecodePathname}). These requests are
94
+ * rejected with a `400` before middleware or routing run.
95
+ */
96
+ invalidEncoding = false;
91
97
  /** A flag that tells the render content if the rewriting was triggered. */
92
98
  isRewriting = false;
93
99
  /** A safety net in case of loops (rewrite counter). */
@@ -111,6 +117,10 @@ class FetchState {
111
117
  clientAddress;
112
118
  /** Whether this is a partial render (container API). */
113
119
  partial;
120
+ /** Internal metadata about the current response route type. */
121
+ responseRouteType;
122
+ /** Internal flag to prevent rerouting this response to an error page. */
123
+ skipErrorReroute = false;
114
124
  /** Whether to inject CSP meta tags. */
115
125
  shouldInjectCspMetaTags;
116
126
  /** Request-scoped locals object, shared with user middleware. */
@@ -697,6 +707,10 @@ class FetchState {
697
707
  try {
698
708
  return validateAndDecodePathname(pathname);
699
709
  } catch (e) {
710
+ if (e instanceof MultiLevelEncodingError) {
711
+ this.invalidEncoding = true;
712
+ return pathname;
713
+ }
700
714
  this.pipeline.logger.error(null, e.toString());
701
715
  return pathname;
702
716
  }
@@ -876,6 +890,10 @@ class FetchState {
876
890
  this.actionApiContext = null;
877
891
  this.apiContext = null;
878
892
  }
893
+ resetResponseMetadata() {
894
+ this.responseRouteType = void 0;
895
+ this.skipErrorReroute = false;
896
+ }
879
897
  }
880
898
  export {
881
899
  FetchState,
@@ -13,13 +13,18 @@ export declare function astro(state: FetchState): Promise<Response>;
13
13
  export declare function trailingSlash(state: FetchState): Response | undefined;
14
14
  /**
15
15
  * Runs Astro's middleware chain for the given state, calling `next` at
16
- * the bottom of the chain to produce the response. Lazily creates
17
- * the render context if needed.
16
+ * the bottom of the chain to produce the response. Lazily creates the
17
+ * render context if needed. Unmatched routes render the 404 error page;
18
+ * errors thrown by user middleware are logged and render the 500 error
19
+ * page; errors surfaced through `next` (the host framework's downstream
20
+ * chain) propagate to the host instead.
18
21
  */
19
22
  export declare function middleware(state: FetchState, next: (state: FetchState) => Promise<Response>): Promise<Response>;
20
23
  /**
21
24
  * Dispatches the request to the matched route (endpoint, page, redirect,
22
- * or fallback). Lazily creates the render context if needed.
25
+ * or fallback). Lazily creates the render context if needed. Unmatched
26
+ * routes render the 404 error page; render-time errors are logged and
27
+ * render the 500 error page.
23
28
  */
24
29
  export declare function pages(state: FetchState): Promise<Response>;
25
30
  /**
@@ -51,7 +51,7 @@ function middleware(state, next) {
51
51
  mw = new AstroMiddleware(app.pipeline);
52
52
  middlewareInstances.set(app, mw);
53
53
  }
54
- return mw.handle(state, (s, _ctx) => next(s));
54
+ return mw.handleWithErrorFallback(app, state, (s, _ctx) => next(s));
55
55
  }
56
56
  const pagesHandlers = /* @__PURE__ */ new WeakMap();
57
57
  function pages(state) {
@@ -61,7 +61,7 @@ function pages(state) {
61
61
  handler = new PagesHandler(app.pipeline);
62
62
  pagesHandlers.set(app, handler);
63
63
  }
64
- return handler.handle(state, state.getAPIContext());
64
+ return handler.handleWithErrorFallback(app, state);
65
65
  }
66
66
  function sessions(state) {
67
67
  return provideSession(state);
@@ -3,7 +3,6 @@ import { computeFallbackRoute } from "../../i18n/fallback.js";
3
3
  import { I18nRouter } from "../../i18n/router.js";
4
4
  import { PipelineFeatures } from "../base-pipeline.js";
5
5
  import { shouldAppendForwardSlash } from "../build/util.js";
6
- import { REROUTE_DIRECTIVE_HEADER, ROUTE_TYPE_HEADER } from "../constants.js";
7
6
  class I18n {
8
7
  #i18n;
9
8
  #base;
@@ -36,25 +35,20 @@ class I18n {
36
35
  async finalize(state, response) {
37
36
  state.pipeline.usedFeatures |= PipelineFeatures.i18n;
38
37
  const i18n = this.#i18n;
39
- const typeHeader = response.headers.get(ROUTE_TYPE_HEADER);
40
- if (typeHeader) {
41
- response.headers.delete(ROUTE_TYPE_HEADER);
42
- }
43
- const isReroute = response.headers.get(REROUTE_DIRECTIVE_HEADER);
44
- if (isReroute === "no" && typeof i18n.fallback === "undefined") {
38
+ if (state.skipErrorReroute && typeof i18n.fallback === "undefined") {
45
39
  return response;
46
40
  }
47
- if (typeHeader !== "page" && typeHeader !== "fallback") {
41
+ if (state.responseRouteType !== "page" && state.responseRouteType !== "fallback") {
48
42
  return response;
49
43
  }
50
- const url = new URL(state.request.url);
44
+ const url = state.url;
51
45
  const currentLocale = state.computeCurrentLocale();
52
46
  const isPrerendered = state.routeData.prerender;
53
47
  const routerContext = {
54
48
  currentLocale,
55
49
  currentDomain: url.hostname,
56
- routeType: typeHeader,
57
- isReroute: isReroute === "yes"
50
+ routeType: state.responseRouteType,
51
+ isReroute: false
58
52
  };
59
53
  const routeDecision = this.#router.match(url.pathname, routerContext);
60
54
  switch (routeDecision.type) {
@@ -74,7 +68,7 @@ class I18n {
74
68
  status: 404,
75
69
  headers: response.headers
76
70
  });
77
- prerenderedRes.headers.set(REROUTE_DIRECTIVE_HEADER, "no");
71
+ state.skipErrorReroute = true;
78
72
  if (routeDecision.location) {
79
73
  prerenderedRes.headers.set("Location", routeDecision.location);
80
74
  }
@@ -90,7 +84,7 @@ class I18n {
90
84
  break;
91
85
  }
92
86
  if (i18n.fallback && i18n.fallbackType) {
93
- const effectiveStatus = typeHeader === "fallback" ? 404 : response.status;
87
+ const effectiveStatus = state.responseRouteType === "fallback" ? 404 : response.status;
94
88
  const fallbackDecision = computeFallbackRoute({
95
89
  pathname: url.pathname,
96
90
  responseStatus: effectiveStatus,
@@ -269,7 +269,7 @@ function printHelp({
269
269
  message.push(
270
270
  linebreak(),
271
271
  ` ${bgGreen(black(` ${commandName} `))} ${green(
272
- `v${"7.0.0-beta.4"}`
272
+ `v${"7.0.0-beta.6"}`
273
273
  )} ${headline}`
274
274
  );
275
275
  }