Redirect Rule Input

Catches redirect rules that loop, chain, shadow each other, open-redirect, drop queries or switch POST to GET, modelled on how each platform matches.

StopsRedirect loop broke the site

Installation

pnpm dlx shadcn@latest add https://bollard-ui.vercel.app/r/redirect-rule-input.json

The files land in your project. They're yours to edit.

Usage

redirect-rule-input-usage.tsx
import { RedirectRuleInput } from "@/components/ui/redirect-rule-input"

<RedirectRuleInput key={example} value={value} onValueChange={setValue} origin="https://example.com" />

What it catches

  • Loops and 2+ hop chains, with the hop path
  • Rules shadowed by an earlier wildcard
  • Open redirects whose destination host comes from the request
  • 301/308 on temporary moves and 301/302 turning POST into GET
  • Dropped query strings, ?query or #hash in the source, missing leading slash, unmatched placeholders
  • Trailing-slash traps and hops to http

Props

RedirectRuleInput props
PropTypeDefault
value

Controlled rules text.

string—
defaultValue

Initial rules text when uncontrolled.

string""
onValueChange

Called with the new text on every edit or fix.

(value: string) => void—
format

Force a format instead of detecting it from the pasted text.

RedirectFormat—
origin

Your site's origin, used for paths without a host. Default https://example.com.

string—
hosts

Other hostnames of the same site (www, apex, old domains), so hops between them are followed.

string[]—
defaultTraceUrl

URL the tester starts with. Defaults to an example from the first loop or chain.

string—
defaultTraceMethod

Method the tester starts with.

RedirectMethod"GET"
temporaryPattern

Paths that look like temporary moves. Defaults to TEMPORARY_PATTERN (sale, promo, maintenance, beta…).

RegExp—
postPattern

Paths likely to receive POSTs. Defaults to POST_PATTERN (api, webhook, checkout, form…).

RegExp—
label

Visible label; shorthand for `messages.label`.

string—
messages

Every visible string. `{detail}`, `{line}`, `{to}`, `{status}`, `{count}`, `{format}` are filled in.

Partial<RedirectRuleInputMessages>—

* required. Also accepts the native props of <textarea> (className, aria-*, data-*…), passed through to it.

Accessibility

  • Visible <label> on the textarea; aria-invalid when errors exist and status wired via aria-describedby
  • Issue count is a role=status region
  • GET/POST tester is a roving-tabindex radiogroup operated with arrow keys
  • After a fix, focus moves to the next fix button or back to the textarea
  • Hop outcomes shown with icons and text

Only what the source does. Test with your own screen reader and content before shipping.

Limitations

This is a UX guard rail. Enforce on the server: Validate redirect destinations against an allowlist on the server; this checks config text, not live traffic.

  • Models each platform from its docs; framework middleware, headers/has conditions and server config elsewhere are not evaluated
  • nginx support covers rewrite/return and location selection, not every module or include
  • Open-redirect detection is pattern-based; review any destination built from user input

Rules

Rules last verified:

Confirmed on Vercel (permanent defaults to true = 308, source is case-sensitive) and Netlify (default 301, 307 unsupported, query passed for 200/301/302, trailing slash ignored when matching). nginx behaviour not re-checked this round. Platforms change; check their docs. Copied components don't update themselves, so re-check after rule changes (see updating a component).

What it stops

Redirect loop broke the site

Also known as

redirects · vercel.json · netlify _redirects · nginx · 301 · 308 · seo · rewrite rules

Field type

Dependencies

Pairs well with