Skip to content

fix: validate redirect status codes in NextResponse.redirect()#759

Merged
james-elicx merged 1 commit intocloudflare:mainfrom
NathanDrake2406:fix/redirect-status-validation
Apr 3, 2026
Merged

fix: validate redirect status codes in NextResponse.redirect()#759
james-elicx merged 1 commit intocloudflare:mainfrom
NathanDrake2406:fix/redirect-status-validation

Conversation

@NathanDrake2406
Copy link
Copy Markdown
Contributor

Summary

  • NextResponse.redirect() accepted any status code without validation
  • redirect(url, 200) silently created a non-redirect response — browser won't follow Location header on non-3xx status
  • Now throws RangeError for invalid redirect status codes (anything not 301/302/303/307/308), matching Next.js behavior

Test plan

  • Test: redirect(url, 200) throws RangeError
  • Test: redirect(url, 418) throws RangeError
  • Test: error message matches Next.js format
  • Test: redirect(url, 303) succeeds (was missing coverage)
  • Test: redirect(url, 307) defaults correctly (existing, regression)
  • Existing server shim tests pass (17/17)

NextResponse.redirect() accepted any numeric status code without
validation. Passing an invalid code like 200 silently created a
non-redirect response (browser ignores Location header on 200).
Now throws RangeError for non-redirect status codes, matching Next.js
behavior which throws on invalid codes.

Valid codes: 301, 302, 303, 307, 308.
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Apr 3, 2026

Open in StackBlitz

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

commit: 67f1223

@james-elicx
Copy link
Copy Markdown
Collaborator

/bigbonk review

Copy link
Copy Markdown
Contributor

@ask-bonk ask-bonk bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean, correct fix. The implementation matches Next.js's NextResponse.redirect() validation exactly — same REDIRECTS set, same RangeError type, same error message. Tests cover the key cases.

One minor suggestion below for test completeness, but not blocking.

expect(() => NextResponse.redirect("https://example.com", 200)).toThrow(
/Failed to execute "redirect" on "response": Invalid status code/,
);
});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: the current tests only cover the init: number overload. It would be worth adding a case for the init: ResponseInit overload with an invalid status, since that's a separate code path through the ternary on line 197 of server.ts:

Suggested change
});
});
it("throws RangeError when status is passed via ResponseInit object", async () => {
const { NextResponse } = await import("../packages/vinext/src/shims/server.js");
expect(() => NextResponse.redirect("https://example.com", { status: 200 })).toThrow(RangeError);
});

@ask-bonk
Copy link
Copy Markdown
Contributor

ask-bonk bot commented Apr 3, 2026

Review submitted. Here's a summary:

Approved — the fix is correct and matches Next.js behavior exactly.

What the PR does: Adds validation to NextResponse.redirect() so that non-redirect status codes (anything other than 301/302/303/307/308) throw a RangeError, preventing silent creation of non-redirect responses that browsers would ignore.

Verification: I confirmed against the Next.js source that:

  • The REDIRECTS set is identical: {301, 302, 303, 307, 308}
  • The error type (RangeError) and message match exactly
  • The validation placement (after status extraction, before header creation) is the same

One minor suggestion: The tests only cover the init: number overload. I suggested adding a test for the init: ResponseInit object overload (e.g., { status: 200 }) since that exercises a different branch of the ternary at server.ts:197.

github run

@james-elicx james-elicx merged commit 9afb1d9 into cloudflare:main Apr 3, 2026
24 checks passed
@NathanDrake2406 NathanDrake2406 deleted the fix/redirect-status-validation branch April 3, 2026 11:46
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.

2 participants