diff --git a/.changeset/wise-bikes-fix.md b/.changeset/wise-bikes-fix.md new file mode 100644 index 000000000000..96628546e8a3 --- /dev/null +++ b/.changeset/wise-bikes-fix.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Add warning when using headers and encoding in endpoints in SSR diff --git a/packages/astro/src/core/app/index.ts b/packages/astro/src/core/app/index.ts index c9ec49bd3c20..c97131b43b73 100644 --- a/packages/astro/src/core/app/index.ts +++ b/packages/astro/src/core/app/index.ts @@ -5,14 +5,13 @@ import type { RouteData, SSRElement, } from '../../@types/astro'; -import type { LogOptions } from '../logger/core.js'; import type { RouteInfo, SSRManifest as Manifest } from './types'; import mime from 'mime'; import { attachToResponse, getSetCookiesFromResponse } from '../cookies/index.js'; import { call as callEndpoint } from '../endpoint/index.js'; import { consoleLogDestination } from '../logger/console.js'; -import { error } from '../logger/core.js'; +import { error, type LogOptions } from '../logger/core.js'; import { joinPaths, prependForwardSlash, removeTrailingForwardSlash } from '../path.js'; import { createEnvironment, @@ -228,7 +227,7 @@ export class App { status, }); - const result = await callEndpoint(handler, this.#env, ctx); + const result = await callEndpoint(handler, this.#env, ctx, this.#logging); if (result.type === 'response') { if (result.response.headers.get('X-Astro-Response') === 'Not-Found') { diff --git a/packages/astro/src/core/build/generate.ts b/packages/astro/src/core/build/generate.ts index 3b163611ae75..7ae4de6a1e23 100644 --- a/packages/astro/src/core/build/generate.ts +++ b/packages/astro/src/core/build/generate.ts @@ -386,7 +386,7 @@ async function generatePath( let encoding: BufferEncoding | undefined; if (pageData.route.type === 'endpoint') { const endpointHandler = mod as unknown as EndpointHandler; - const result = await callEndpoint(endpointHandler, env, ctx); + const result = await callEndpoint(endpointHandler, env, ctx, logging); if (result.type === 'response') { throwIfRedirectNotAllowed(result.response, opts.settings.config); diff --git a/packages/astro/src/core/endpoint/dev/index.ts b/packages/astro/src/core/endpoint/dev/index.ts index 889b82345fce..515b7aa41a8e 100644 --- a/packages/astro/src/core/endpoint/dev/index.ts +++ b/packages/astro/src/core/endpoint/dev/index.ts @@ -1,9 +1,10 @@ import type { EndpointHandler } from '../../../@types/astro'; +import type { LogOptions } from '../../logger/core'; import type { SSROptions } from '../../render/dev'; import { createRenderContext } from '../../render/index.js'; import { call as callEndpoint } from '../index.js'; -export async function call(options: SSROptions) { +export async function call(options: SSROptions, logging: LogOptions) { const { env, preload: [, mod], @@ -17,5 +18,5 @@ export async function call(options: SSROptions) { route: options.route, }); - return await callEndpoint(endpointHandler, env, ctx); + return await callEndpoint(endpointHandler, env, ctx, logging); } diff --git a/packages/astro/src/core/endpoint/index.ts b/packages/astro/src/core/endpoint/index.ts index 533bebddd2df..fbfa8cfd40b3 100644 --- a/packages/astro/src/core/endpoint/index.ts +++ b/packages/astro/src/core/endpoint/index.ts @@ -5,6 +5,7 @@ import { renderEndpoint } from '../../runtime/server/index.js'; import { ASTRO_VERSION } from '../constants.js'; import { AstroCookies, attachToResponse } from '../cookies/index.js'; import { AstroError, AstroErrorData } from '../errors/index.js'; +import { LogOptions, warn } from '../logger/core.js'; import { getParamsAndProps, GetParamsAndPropsError } from '../render/core.js'; const clientAddressSymbol = Symbol.for('astro.clientAddress'); @@ -71,7 +72,8 @@ function createAPIContext({ export async function call( mod: EndpointHandler, env: Environment, - ctx: RenderContext + ctx: RenderContext, + logging: LogOptions ): Promise { const paramsAndPropsResp = await getParamsAndProps({ mod: mod as any, @@ -111,6 +113,24 @@ export async function call( }; } + if (env.ssr && !mod.prerender) { + if (response.hasOwnProperty('headers')) { + warn( + logging, + 'ssr', + 'Setting headers is not supported when returning an object. Please return an instance of Response. See https://docs.astro.build/en/core-concepts/endpoints/#server-endpoints-api-routes for more information.' + ); + } + + if (response.encoding) { + warn( + logging, + 'ssr', + '`encoding` is ignored in SSR. To return a charset other than UTF-8, please return an instance of Response. See https://docs.astro.build/en/core-concepts/endpoints/#server-endpoints-api-routes for more information.' + ); + } + } + return { type: 'simple', body: response.body, diff --git a/packages/astro/src/vite-plugin-astro-server/route.ts b/packages/astro/src/vite-plugin-astro-server/route.ts index 85643034f995..d26fc62d70e5 100644 --- a/packages/astro/src/vite-plugin-astro-server/route.ts +++ b/packages/astro/src/vite-plugin-astro-server/route.ts @@ -172,7 +172,7 @@ export async function handleRoute( // Route successfully matched! Render it. if (route.type === 'endpoint') { - const result = await callEndpoint(options); + const result = await callEndpoint(options, logging); if (result.type === 'response') { if (result.response.headers.get('X-Astro-Response') === 'Not-Found') { const fourOhFourRoute = await matchRoute('/404', env, manifest);