diff --git a/.changeset/sweet-zoos-move.md b/.changeset/sweet-zoos-move.md new file mode 100644 index 000000000000..7c027a94483a --- /dev/null +++ b/.changeset/sweet-zoos-move.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Fixes a bug where users could use `Astro.request.headers` during a rewrite inside prerendered routes. This an invalid behaviour, and now Astro will show a warning if this happens. diff --git a/.changeset/tame-pianos-approve.md b/.changeset/tame-pianos-approve.md new file mode 100644 index 000000000000..136c1dae93f6 --- /dev/null +++ b/.changeset/tame-pianos-approve.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Fixes an issue where the use of `Astro.rewrite` would trigger the invalid use of `Astro.request.headers` diff --git a/packages/astro/src/core/render-context.ts b/packages/astro/src/core/render-context.ts index db88275961a9..3e0637ed8edf 100644 --- a/packages/astro/src/core/render-context.ts +++ b/packages/astro/src/core/render-context.ts @@ -175,7 +175,14 @@ export class RenderContext { if (payload instanceof Request) { this.request = payload; } else { - this.request = copyRequest(newUrl, this.request); + this.request = copyRequest( + newUrl, + this.request, + // need to send the flag of the previous routeData + routeData.prerender, + this.pipeline.logger, + this.routeData.route, + ); } this.isRewriting = true; this.url = new URL(this.request.url); @@ -290,7 +297,14 @@ export class RenderContext { if (reroutePayload instanceof Request) { this.request = reroutePayload; } else { - this.request = copyRequest(newUrl, this.request); + this.request = copyRequest( + newUrl, + this.request, + // need to send the flag of the previous routeData + routeData.prerender, + this.pipeline.logger, + this.routeData.route, + ); } this.url = new URL(this.request.url); this.cookies = new AstroCookies(this.request); diff --git a/packages/astro/src/core/request.ts b/packages/astro/src/core/request.ts index 302370ba8d61..289920403240 100644 --- a/packages/astro/src/core/request.ts +++ b/packages/astro/src/core/request.ts @@ -2,14 +2,20 @@ import type { IncomingHttpHeaders } from 'node:http'; import type { Logger } from './logger/core.js'; type HeaderType = Headers | Record | IncomingHttpHeaders; -type RequestBody = ArrayBuffer | Blob | ReadableStream | URLSearchParams | FormData; +type RequestBody = + | ArrayBuffer + | Blob + | ReadableStream + | URLSearchParams + | FormData + | ReadableStream; export interface CreateRequestOptions { url: URL | string; clientAddress?: string | undefined; headers: HeaderType; method?: string; - body?: RequestBody | undefined; + body?: RequestBody | undefined | null; logger: Logger; locals?: object | undefined; /** @@ -22,6 +28,8 @@ export interface CreateRequestOptions { isPrerendered?: boolean; routePattern: string; + + init?: RequestInit; } /** @@ -39,6 +47,7 @@ export function createRequest({ logger, isPrerendered = false, routePattern, + init, }: CreateRequestOptions): Request { // headers are made available on the created request only if the request is for a page that will be on-demand rendered const headersObj = isPrerendered @@ -65,6 +74,7 @@ export function createRequest({ headers: headersObj, // body is made available only if the request is for a page that will be on-demand rendered body: isPrerendered ? null : body, + ...init, }); if (isPrerendered) { diff --git a/packages/astro/src/core/routing/rewrite.ts b/packages/astro/src/core/routing/rewrite.ts index 57709892eada..40f91441316b 100644 --- a/packages/astro/src/core/routing/rewrite.ts +++ b/packages/astro/src/core/routing/rewrite.ts @@ -4,7 +4,9 @@ import type { RouteData } from '../../types/public/internal.js'; import { shouldAppendForwardSlash } from '../build/util.js'; import { originPathnameSymbol } from '../constants.js'; import { AstroError, AstroErrorData } from '../errors/index.js'; +import type { Logger } from '../logger/core.js'; import { appendForwardSlash, removeTrailingForwardSlash } from '../path.js'; +import { createRequest } from '../request.js'; import { DEFAULT_404_ROUTE } from './astro-designed-error-pages.js'; export type FindRouteToRewrite = { @@ -80,27 +82,42 @@ export function findRouteToRewrite({ * * @param newUrl The new `URL` * @param oldRequest The old `Request` + * @param isPrerendered It needs to be the flag of the previous routeData, before the rewrite + * @param logger + * @param routePattern */ -export function copyRequest(newUrl: URL, oldRequest: Request): Request { +export function copyRequest( + newUrl: URL, + oldRequest: Request, + isPrerendered: boolean, + logger: Logger, + routePattern: string, +): Request { if (oldRequest.bodyUsed) { throw new AstroError(AstroErrorData.RewriteWithBodyUsed); } - return new Request(newUrl, { + return createRequest({ + url: newUrl, method: oldRequest.method, - headers: oldRequest.headers, body: oldRequest.body, - referrer: oldRequest.referrer, - referrerPolicy: oldRequest.referrerPolicy, - mode: oldRequest.mode, - credentials: oldRequest.credentials, - cache: oldRequest.cache, - redirect: oldRequest.redirect, - integrity: oldRequest.integrity, - signal: oldRequest.signal, - keepalive: oldRequest.keepalive, - // https://fetch.spec.whatwg.org/#dom-request-duplex - // @ts-expect-error It isn't part of the types, but undici accepts it and it allows to carry over the body to a new request - duplex: 'half', + isPrerendered, + logger, + headers: isPrerendered ? {} : oldRequest.headers, + routePattern, + init: { + referrer: oldRequest.referrer, + referrerPolicy: oldRequest.referrerPolicy, + mode: oldRequest.mode, + credentials: oldRequest.credentials, + cache: oldRequest.cache, + redirect: oldRequest.redirect, + integrity: oldRequest.integrity, + signal: oldRequest.signal, + keepalive: oldRequest.keepalive, + // https://fetch.spec.whatwg.org/#dom-request-duplex + // @ts-expect-error It isn't part of the types, but undici accepts it and it allows to carry over the body to a new request + duplex: 'half', + }, }); }