Skip to content

fix(cloudflare): return redirects from cache-facing fetches - #3242

Open
JamesbbBriz wants to merge 2 commits into
cloudflare:mainfrom
JamesbbBriz:fix/cached-stage-redirect-loop
Open

JamesbbBriz wants to merge 2 commits into
cloudflare:mainfrom
JamesbbBriz:fix/cached-stage-redirect-loop

Conversation

@JamesbbBriz

@JamesbbBriz JamesbbBriz commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

Problem

Since #3168 (35af7910), any shared-cache App or Pages render that responds with a redirect returns 500 TypeError: Too many redirects instead of surfacing the redirect to the client.

A Payload CMS /admin route exposed this: unauthenticated visitors should receive 307 -> /admin/login, but the request instead exhausted the Workers redirect budget.

Fixes #3243.

Root cause

createCacheFacingRequest intentionally constructs a fresh Request so browser cache-bypass state does not leak into the cache-enabled entrypoint. A fresh Workers Request defaults to redirect: "follow", unlike the client-originated Worker request whose mode is manual.

When a response-stage render returns a redirect, following it re-enters the cache entrypoint for the destination while the configurable-entrypoint invocation still describes the original route. The original route renders and redirects again until workerd exhausts its redirect limit.

Cloudflare also documents that followed redirects forward request headers to the destination, including cross-origin destinations, so the cache-stage transport must treat a render redirect as its terminal response.

Fix

Set redirect: "manual" on the single cache-facing request factory. This returns the 3xx response to the uncached gateway, preserves its status and Location, and matches the pre-#3168 gateway behavior.

The same factory serves both App and Pages shared response stages. Bypass/probe stages keep their direct request path.

Parity

Next.js document requests surface redirect() as a 307. The runtime regression ports that invariant from:

https://github.com/vercel/next.js/blob/canary/test/e2e/app-dir/rsc-redirect/rsc-redirect.test.ts

Validation

  • Added focused unit coverage that asserts the cache-facing request uses manual redirect handling.
  • Added a real Wrangler/workerd regression for an App Router redirect() and a Pages Router getStaticProps redirect, with client redirect following disabled.
  • Baseline without the fix: 500 TypeError: Too many redirects, with 20 repeated destination hops.
  • With the fix: both App and Pages routes return 307 with the expected Location.
  • vp test run tests/cloudflare-cdn-worker.test.ts: 60/60 passed.
  • Targeted vp check: formatting, lint, and types passed.
  • vp run @vinext/cloudflare#build: passed.

A fetch through the cache-enabled response entrypoint follows redirects
by default. When a shared-cache render responds with a redirect, the
runtime follows it and re-enters the entrypoint for the redirect target
while the response-stage invocation still describes the original URL —
so the redirect source re-renders and redirects again, until the
runtime's redirect budget is exhausted (TypeError: Too many redirects).

Observed on a Payload CMS app whose /admin route redirects
unauthenticated visitors to /admin/login: every hop logged another
/admin/login render performed with the original /admin invocation, and
the page 500ed. Bisected to 35af791 (cloudflare#3168), which routes public
traffic through the cache-fronted entrypoint.

Set redirect: manual on the cache-facing request so redirect responses
are returned to the caller, matching the pre-cloudflare#3168 gateway behavior.
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@pkg-pr-new

pkg-pr-new Bot commented Sep 11, 2026

Copy link
Copy Markdown

Open in StackBlitz

@vinext/cloudflare

npm i https://pkg.pr.new/@vinext/cloudflare@3242

create-vinext-app

npm i https://pkg.pr.new/create-vinext-app@3242

@vinext/types

npm i https://pkg.pr.new/@vinext/types@3242

vinext

npm i https://pkg.pr.new/vinext@3242

@cloudflare/workers-response-store

npm i https://pkg.pr.new/@cloudflare/workers-response-store@3242

commit: 88cb127

JamesbbBriz added a commit to JamesbbBriz/vinext that referenced this pull request Sep 11, 2026
@github-actions

github-actions Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

Performance benchmarks

Compared 88cb127 against base e97de29 using alternating same-runner rounds. Next.js was unchanged and skipped.

0 improved · 0 regressed · 6 within ±1.5%

Scenario Framework Baseline Current Change
Client bundle size (gzip) vinext 142.2 KB 142.2 KB ⚫ +0.0%
Client entry size (gzip) vinext 129.6 KB 129.6 KB ⚫ +0.0%
Dev server cold start vinext 3.14 s 3.14 s ⚫ +0.2%
Production build time vinext 3.44 s 3.49 s ⚫ +1.5%
RSC entry closure size (gzip) vinext 121.0 KB 121.0 KB ⚫ -0.0%
Server bundle size (gzip) vinext 218.3 KB 218.3 KB ⚫ -0.0%

View detailed results and traces

🟢 improvement · 🔴 regression · ⚫ change below 1.5% · paired base/head

@james-elicx

Copy link
Copy Markdown
Member

/bigbonk review for issues

Time limit: 8 minutes. Complete the review and post all findings within that limit.

@ask-bonk

ask-bonk Bot commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

@james-elicx Bonk workflow was cancelled.

View workflow run · To retry, trigger Bonk again.

@james-elicx
james-elicx force-pushed the fix/cached-stage-redirect-loop branch from 63b5e03 to 43f4ff4 Compare September 17, 2026 13:48
@james-elicx
james-elicx force-pushed the fix/cached-stage-redirect-loop branch from 43f4ff4 to 88cb127 Compare September 17, 2026 13:48
@james-elicx

Copy link
Copy Markdown
Member

/bigbonk review for issues

Time limit: 8 minutes. Complete the review and post all findings within that limit.

@ask-bonk

ask-bonk Bot commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

LGTM!

github run

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Shared-cache renders that redirect return 500 "Too many redirects" since #3168

2 participants