diff --git a/.changeset/five-kids-double.md b/.changeset/five-kids-double.md new file mode 100644 index 000000000000..1c00067d8bec --- /dev/null +++ b/.changeset/five-kids-double.md @@ -0,0 +1,8 @@ +--- +'@astrojs/cloudflare': patch +--- +Fixes unnecessary prerendering of redirect destinations + +Unnecessary files are no longer generated by static builds for redirected routes. + +Requests are no longer made at build time to external redirect destination URLs, which could cause builds to fail. diff --git a/packages/integrations/cloudflare/src/prerenderer.ts b/packages/integrations/cloudflare/src/prerenderer.ts index 8b452ab7b22a..f55a8a9a036e 100644 --- a/packages/integrations/cloudflare/src/prerenderer.ts +++ b/packages/integrations/cloudflare/src/prerenderer.ts @@ -116,6 +116,7 @@ export function createCloudflarePrerenderer({ method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body), + redirect: 'manual', }); return response; diff --git a/packages/integrations/cloudflare/test/external-redirects.test.js b/packages/integrations/cloudflare/test/external-redirects.test.js new file mode 100644 index 000000000000..33e841c0c0fe --- /dev/null +++ b/packages/integrations/cloudflare/test/external-redirects.test.js @@ -0,0 +1,37 @@ +import { describe, it } from 'node:test'; +import { loadFixture } from './_test-utils.js'; +import assert from 'node:assert/strict'; +import { existsSync, readFileSync } from 'node:fs'; +import { fileURLToPath } from 'node:url'; + +describe('External Redirects', () => { + let fixture; + + it('should not attempt to prerender external redirect destinations', async () => { + fixture = await loadFixture({ + root: './fixtures/external-redirects', + }); + + // Building should not result in a fetch to the external destination URL. + // If it does, the fetch will throw and the test will fail. + await fixture.build(); + + // Check that the redirect file was created and contains the redirect + const redirectsPath = fileURLToPath(new URL('client/_redirects', fixture.config.outDir)); + const redirectsContent = readFileSync(redirectsPath, 'utf-8'); + assert.match( + redirectsContent, + /\/redirect\s+http:\/\/test.invalid\/destination\s+301/, + '_redirects file should contain the redirect rule', + ); + + // Check that the destination was not prerendered + const prerenderedPath = fileURLToPath( + new URL('client/redirect/index.html', fixture.config.outDir), + ); + assert.ok( + !existsSync(prerenderedPath), + 'Should not create prerendered file for external redirect destination', + ); + }); +}); diff --git a/packages/integrations/cloudflare/test/fixtures/external-redirects/astro.config.mjs b/packages/integrations/cloudflare/test/fixtures/external-redirects/astro.config.mjs new file mode 100644 index 000000000000..0f4c3323c8ab --- /dev/null +++ b/packages/integrations/cloudflare/test/fixtures/external-redirects/astro.config.mjs @@ -0,0 +1,10 @@ +import { defineConfig } from "astro/config"; +import cloudflare from "@astrojs/cloudflare"; + +export default defineConfig({ + adapter: cloudflare(), + output: 'static', + redirects: { + "/redirect": "http://test.invalid/destination", + }, +}); diff --git a/packages/integrations/cloudflare/test/fixtures/external-redirects/package.json b/packages/integrations/cloudflare/test/fixtures/external-redirects/package.json new file mode 100644 index 000000000000..5db14db0fb94 --- /dev/null +++ b/packages/integrations/cloudflare/test/fixtures/external-redirects/package.json @@ -0,0 +1,12 @@ +{ + "name": "@test/astro-cloudflare-external-redirects", + "version": "0.0.0", + "private": true, + "scripts": { + "build": "astro build" + }, + "dependencies": { + "@astrojs/cloudflare": "workspace:*", + "astro": "workspace:*" + } +} diff --git a/packages/integrations/cloudflare/test/fixtures/external-redirects/src/pages/index.astro b/packages/integrations/cloudflare/test/fixtures/external-redirects/src/pages/index.astro new file mode 100644 index 000000000000..58aa0a19513c --- /dev/null +++ b/packages/integrations/cloudflare/test/fixtures/external-redirects/src/pages/index.astro @@ -0,0 +1,10 @@ +--- +--- + + + External Redirects Test + + +

External Redirects Test

+ + diff --git a/packages/integrations/cloudflare/test/fixtures/internal-redirects/astro.config.mjs b/packages/integrations/cloudflare/test/fixtures/internal-redirects/astro.config.mjs new file mode 100644 index 000000000000..9fc108b65cdb --- /dev/null +++ b/packages/integrations/cloudflare/test/fixtures/internal-redirects/astro.config.mjs @@ -0,0 +1,10 @@ +import { defineConfig } from "astro/config"; +import cloudflare from "@astrojs/cloudflare"; + +export default defineConfig({ + adapter: cloudflare(), + output: 'static', + redirects: { + "/redirect": '/page2' + }, +}); diff --git a/packages/integrations/cloudflare/test/fixtures/internal-redirects/package.json b/packages/integrations/cloudflare/test/fixtures/internal-redirects/package.json new file mode 100644 index 000000000000..02231004d3f7 --- /dev/null +++ b/packages/integrations/cloudflare/test/fixtures/internal-redirects/package.json @@ -0,0 +1,12 @@ +{ + "name": "@test/astro-cloudflare-internal-redirects", + "version": "0.0.0", + "private": true, + "scripts": { + "build": "astro build" + }, + "dependencies": { + "@astrojs/cloudflare": "workspace:*", + "astro": "workspace:*" + } +} diff --git a/packages/integrations/cloudflare/test/fixtures/internal-redirects/src/pages/index.astro b/packages/integrations/cloudflare/test/fixtures/internal-redirects/src/pages/index.astro new file mode 100644 index 000000000000..46fb003a43fe --- /dev/null +++ b/packages/integrations/cloudflare/test/fixtures/internal-redirects/src/pages/index.astro @@ -0,0 +1,10 @@ +--- +--- + + + Internal Redirects Test + + +

Internal Redirects Test

+ + diff --git a/packages/integrations/cloudflare/test/fixtures/internal-redirects/src/pages/page2.astro b/packages/integrations/cloudflare/test/fixtures/internal-redirects/src/pages/page2.astro new file mode 100644 index 000000000000..1a4688aca9e8 --- /dev/null +++ b/packages/integrations/cloudflare/test/fixtures/internal-redirects/src/pages/page2.astro @@ -0,0 +1,10 @@ +--- +--- + + + Page 2 + + +

Page 2

+ + diff --git a/packages/integrations/cloudflare/test/internal-redirects.test.js b/packages/integrations/cloudflare/test/internal-redirects.test.js new file mode 100644 index 000000000000..84ae0d251b6b --- /dev/null +++ b/packages/integrations/cloudflare/test/internal-redirects.test.js @@ -0,0 +1,35 @@ +import { describe, it } from 'node:test'; +import { loadFixture } from './_test-utils.js'; +import assert from 'node:assert/strict'; +import { existsSync, readFileSync } from 'node:fs'; +import { fileURLToPath } from 'node:url'; + +describe('Internal Redirects', () => { + let fixture; + + it('should not create a prerendered file for internal redirects', async () => { + fixture = await loadFixture({ + root: './fixtures/internal-redirects', + }); + + await fixture.build(); + + // Check that the redirect file was created and contains the redirect + const redirectsPath = fileURLToPath(new URL('client/_redirects', fixture.config.outDir)); + const redirectsContent = readFileSync(redirectsPath, 'utf-8'); + assert.match( + redirectsContent, + /\/redirect\s+\/page2\s+301/, + '_redirects file should contain the redirect rule', + ); + + // Check that the destination was not prerendered + const prerenderedPath = fileURLToPath( + new URL('client/redirect/index.html', fixture.config.outDir), + ); + assert.ok( + !existsSync(prerenderedPath), + 'Should not create prerendered file for internal redirect destination', + ); + }); +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f5d4ac644efd..9519bfeea1bf 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4982,6 +4982,24 @@ importers: specifier: workspace:* version: link:../../../../../astro + packages/integrations/cloudflare/test/fixtures/external-redirects: + dependencies: + '@astrojs/cloudflare': + specifier: workspace:* + version: link:../../.. + astro: + specifier: workspace:* + version: link:../../../../../astro + + packages/integrations/cloudflare/test/fixtures/internal-redirects: + dependencies: + '@astrojs/cloudflare': + specifier: workspace:* + version: link:../../.. + astro: + specifier: workspace:* + version: link:../../../../../astro + packages/integrations/cloudflare/test/fixtures/no-output: dependencies: '@astrojs/cloudflare':