diff --git a/.changeset/tall-trainers-do.md b/.changeset/tall-trainers-do.md new file mode 100644 index 0000000000..7d67768a36 --- /dev/null +++ b/.changeset/tall-trainers-do.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Throws when using Response.redirect in SSG mode diff --git a/packages/astro/src/vite-plugin-astro-server/index.ts b/packages/astro/src/vite-plugin-astro-server/index.ts index 34707b084d..b3af040b04 100644 --- a/packages/astro/src/vite-plugin-astro-server/index.ts +++ b/packages/astro/src/vite-plugin-astro-server/index.ts @@ -1,7 +1,7 @@ import type http from 'http'; import mime from 'mime'; import type * as vite from 'vite'; -import type { AstroSettings, ManifestData } from '../@types/astro'; +import type { AstroConfig, AstroSettings, ManifestData } from '../@types/astro'; import { DevelopmentEnvironment, SSROptions } from '../core/render/dev/index'; import { Readable } from 'stream'; @@ -296,6 +296,16 @@ 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, @@ -367,6 +377,7 @@ async function handleRoute( res ); } + throwIfRedirectNotAllowed(result.response, config); await writeWebResponse(res, result.response); } else { let contentType = 'text/plain'; @@ -389,6 +400,7 @@ async function handleRoute( } } else { const result = await renderPage(options); + throwIfRedirectNotAllowed(result, config); return await writeSSRResult(result, res); } } diff --git a/packages/astro/test/dev-routing.test.js b/packages/astro/test/dev-routing.test.js index 255d8d2498..7188e1ff0c 100644 --- a/packages/astro/test/dev-routing.test.js +++ b/packages/astro/test/dev-routing.test.js @@ -1,5 +1,4 @@ import { expect } from 'chai'; -import * as cheerio from 'cheerio'; import { loadFixture } from './test-utils.js'; describe('Development Routing', () => { @@ -42,6 +41,11 @@ describe('Development Routing', () => { const response = await fixture.fetch('/2'); expect(response.status).to.equal(404); }); + + it('500 when redirecting in SSG mode', async () => { + const response = await fixture.fetch('/redirect'); + expect(response.status).to.equal(500); + }); }); describe('No subpath used', () => { diff --git a/packages/astro/test/fixtures/without-site-config/src/pages/redirect.astro b/packages/astro/test/fixtures/without-site-config/src/pages/redirect.astro new file mode 100644 index 0000000000..4b640e5b5d --- /dev/null +++ b/packages/astro/test/fixtures/without-site-config/src/pages/redirect.astro @@ -0,0 +1,4 @@ +--- +const anotherURL = new URL('./another/', Astro.url); +return Response.redirect(anotherURL.toString()); +---