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':