From 74759cf787aefeeccc3fc336fdb0a56b982733bb Mon Sep 17 00:00:00 2001 From: Bjorn Lu Date: Tue, 1 Nov 2022 00:58:54 +0800 Subject: [PATCH] Allow 200 response for endpoints in build (#5258) --- .changeset/cool-ducks-mix.md | 5 +++++ packages/astro/src/core/build/generate.ts | 21 ++++++++++--------- packages/astro/src/core/endpoint/index.ts | 14 ++++++++++++- .../src/vite-plugin-astro-server/index.ts | 13 +----------- .../src/pages/invalid-redirect.json.ts | 11 ++++++++++ 5 files changed, 41 insertions(+), 23 deletions(-) create mode 100644 .changeset/cool-ducks-mix.md create mode 100644 packages/astro/test/fixtures/with-endpoint-routes/src/pages/invalid-redirect.json.ts diff --git a/.changeset/cool-ducks-mix.md b/.changeset/cool-ducks-mix.md new file mode 100644 index 000000000..938ecd06d --- /dev/null +++ b/.changeset/cool-ducks-mix.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Allow 200 response for endpoints in build diff --git a/packages/astro/src/core/build/generate.ts b/packages/astro/src/core/build/generate.ts index e89fc0b28..039e8283c 100644 --- a/packages/astro/src/core/build/generate.ts +++ b/packages/astro/src/core/build/generate.ts @@ -21,7 +21,7 @@ import { } from '../../core/path.js'; import { runHookBuildGenerated } from '../../integrations/index.js'; import { BEFORE_HYDRATION_SCRIPT_ID, PAGE_SCRIPT_ID } from '../../vite-plugin-scripts/index.js'; -import { call as callEndpoint } from '../endpoint/index.js'; +import { call as callEndpoint, throwIfRedirectNotAllowed } from '../endpoint/index.js'; import { debug, info } from '../logger/core.js'; import { createEnvironment, createRenderContext, renderPage } from '../render/index.js'; import { callGetStaticPaths } from '../render/route-cache.js'; @@ -374,18 +374,19 @@ async function generatePath( const result = await callEndpoint(endpointHandler, env, ctx); if (result.type === 'response') { - throw new Error(`Returning a Response from an endpoint is not supported in SSG mode.`); + throwIfRedirectNotAllowed(result.response, opts.settings.config); + // If there's no body, do nothing + if (!result.response.body) return; + body = await result.response.text(); + } else { + body = result.body; + encoding = result.encoding; } - body = result.body; - encoding = result.encoding; } else { const response = await renderPage(mod, ctx, env); - - // If there's a redirect or something, just do nothing. - if (response.status !== 200 || !response.body) { - return; - } - + throwIfRedirectNotAllowed(response, opts.settings.config); + // If there's no body, do nothing + if (!response.body) return; body = await response.text(); } diff --git a/packages/astro/src/core/endpoint/index.ts b/packages/astro/src/core/endpoint/index.ts index 79102f8b1..11d6cb664 100644 --- a/packages/astro/src/core/endpoint/index.ts +++ b/packages/astro/src/core/endpoint/index.ts @@ -1,4 +1,4 @@ -import type { APIContext, EndpointHandler, Params } from '../../@types/astro'; +import type { APIContext, AstroConfig, EndpointHandler, Params } from '../../@types/astro'; import type { Environment, RenderContext } from '../render/index'; import { renderEndpoint } from '../../runtime/server/index.js'; @@ -113,3 +113,15 @@ export async function call( cookies: context.cookies, }; } + +function isRedirect(statusCode: number) { + return statusCode >= 300 && statusCode < 400; +} + +export function throwIfRedirectNotAllowed(response: Response, config: AstroConfig) { + if (config.output !== 'server' && isRedirect(response.status)) { + throw new Error( + `Redirects are only available when using output: 'server'. Update your Astro config if you need SSR features.` + ); + } +} diff --git a/packages/astro/src/vite-plugin-astro-server/index.ts b/packages/astro/src/vite-plugin-astro-server/index.ts index bf34f83bc..d98b9344f 100644 --- a/packages/astro/src/vite-plugin-astro-server/index.ts +++ b/packages/astro/src/vite-plugin-astro-server/index.ts @@ -19,6 +19,7 @@ import { createRequest } from '../core/request.js'; import { createRouteManifest, matchAllRoutes } from '../core/routing/index.js'; import { resolvePages } from '../core/util.js'; import notFoundTemplate, { subpathNotUsedTemplate } from '../template/4xx.js'; +import { throwIfRedirectNotAllowed } from '../core/endpoint/index.js'; interface AstroPluginOptions { settings: AstroSettings; @@ -293,18 +294,6 @@ async function handleRequest( } } -function isRedirect(statusCode: number) { - return statusCode >= 300 && statusCode < 400; -} - -function throwIfRedirectNotAllowed(response: Response, config: AstroConfig) { - if (config.output !== 'server' && isRedirect(response.status)) { - throw new Error( - `Redirects are only available when using output: 'server'. Update your Astro config if you need SSR features.` - ); - } -} - async function handleRoute( matchedRoute: AsyncReturnType, url: URL, diff --git a/packages/astro/test/fixtures/with-endpoint-routes/src/pages/invalid-redirect.json.ts b/packages/astro/test/fixtures/with-endpoint-routes/src/pages/invalid-redirect.json.ts new file mode 100644 index 000000000..b1b48634f --- /dev/null +++ b/packages/astro/test/fixtures/with-endpoint-routes/src/pages/invalid-redirect.json.ts @@ -0,0 +1,11 @@ +export const get = () => { + return new Response( + undefined, + { + status: 301, + headers: { + Location: 'https://example.com', + } + } + ); +};