The bounded mapper preserves the encoded path and repeated tag query while replacing only the allowed origin. The baseline returns expected 302 with new.example.invalid/notes/a%20b?tag=one&tag=two. POST returns 405 without Location; a new-origin GET returns 404. The page evaluates a local contract and never performs a request.

Work through the example
Change the request to https://old.example.invalid/notes?next=https://else.example.invalid and Evaluate. The target origin remains new.example.invalid; next stays query data. Change the method to POST to see Allow: GET and no Location. An invalid URL receives an input error rather than a fabricated HTTP response.
Inspect the complete Location and then its parsed origin, path and search. Repeated keys must survive this fixture, and the next value stays data. Do not infer the redirect destination from a query parameter. Test method failures and wrong origins with no Location header, keeping these authored policy checks separate from any routing rules outside the handler.
Fix the origin policy before constructing a target
Use these authored constants:
| Field | Fixed fixture value |
|---|---|
| Allowed source origin | https://old.example.invalid |
| Destination origin/base | https://new.example.invalid |
| Allowed method | GET only |
| Redirect status | 302 |
| Extra target path prefix | None |
Set the destination in the Worker source or configuration, never from a query value, Host header or supplied next parameter. The base has no trailing path prefix; the parsed pathname supplies the slash.
Cloudflare's official example documents Response.redirect and a fixed base combined with parsed pathname and search. Our exact-origin, GET-only and 302 rules are original practice policy, rather than the example's all-request 301 behavior. Cloudflare's redirect mechanisms.
302 indicates a temporary redirect to the Location target. It is the declared practice status here, not a permanent migration or SEO recommendation. MDN's 302 status reference.
Preserve the encoded path and repeated query in the fixture
The main authored request is:
GET https://old.example.invalid/notes/a%20b?tag=one&tag=two
Its expected response fields are:
Status: 302
Location: https://new.example.invalid/notes/a%20b?tag=one&tag=two
Review three pieces separately:
| Piece | Parsed fixture value | Expected use |
|---|---|---|
| Origin | https://old.example.invalid | Exact allowed-origin check |
| Pathname | /notes/a%20b | Append without manual decode/re-encode |
| Search | ?tag=one&tag=two | Append without converting to a one-value dictionary |
The two tag keys remain in this fixture's query string. Do not reduce them to one value, sort them, decode the path into a space and reconstruct it by hand, or infer a new destination from them.
This is a parsed-URL contract. It does not promise byte-for-byte preservation of every possible raw URL spelling; URL parsing and response serialization can normalize inputs. Test the exact selected fixture in the confirmed native environment.
Fragments are outside this HTTP request-mapping scope. Do not invent preservation of a browser fragment from the request contract. MDN's fragment reference.
Keep next as data rather than a destination
For the authored request:
GET https://old.example.invalid/notes?next=https://else.example.invalid
Expect:
Status: 302
Location: https://new.example.invalid/notes?next=https://else.example.invalid
The Location's origin is still new.example.invalid. The next string remains query data. This handler does not interpret it, navigate to it, fetch it, or certify how another application might later handle it.
That distinction should be visible in the native test record. A Location containing the word “else” is not itself evidence that the redirect origin changed; inspect the parsed target origin and the complete header.
The fixture is not a security certificate for an entire site. It checks the bounded rule that this handler never uses an untrusted destination parameter as its own target origin.
Reject other methods and origins under the declared policy
For this packet, validate in this order:
- Hold malformed fixture input before accepting a request/response test case.
- If the method is not GET, return the authored 405 response with no Location.
- Parse the request URL and compare its origin with the exact allowed source.
- A different origin returns the authored 404 response with no Location.
- Only an allowed GET constructs fixed base + parsed pathname + search and returns 302.
Recreate this example
Build one self-contained responsive HTML example titled “Cloudflare redirect: inspect status and Location” for readers completing the stated task. Return the complete HTML with embedded CSS and JavaScript. Use no remote fonts, libraries, images, requests, account connections, or saved-state claims.
Local mapper for allowed source https://old.example.invalid, fixed destination https://new.example.invalid, GET only and 302. URL input defaults /notes/a%20b?tag=one&tag=two on old origin; method input GET. Evaluate parses URL, checks malformed input, then method405 Allow GET no Location, then wrong origin404 no Location, else fixed base+pathname+search. Preserve duplicate query keys without a dictionary and never use next as target. Display literal status/Location or absence. No fetch, navigation, DNS, edge execution or deployment. Label expected response contract, not observed Worker response.
Use an HTTP response workbench with fixed-origin policy and literal header output design with a compact header. Keep the actual sample data, controls, and useful default result visible early on a 360px-wide screen. Use readable text at least 16px, generous paragraph spacing, strong contrast, semantic labels, visible keyboard focus, and wrapping source blocks. Stack records on narrow screens rather than forcing a wide table.
Wire each action to an explicit type=button click handler using element selectors; the host permits scripts but blocks form submission. Update the visible result when the described action occurs. Show specific error feedback for invalid or missing input and clear stale feedback after dependent inputs change. Use plain text when displaying user values.
The local response mapper is not a deployed Worker or an observed edge response. Keep the source fixture and worked teacher or developer example distinct from actual user records. Include the domain-specific explanation and next check beside the result. Provide no fake download, send, deployment, approval, or persistence button. Everything operates locally for the current page session.
Review the prepared copy in NOS
Turn the accepted fixture strings into native Worker response tests that do not follow redirects. For a code-review explanation, NOS can render the HTML mapping table and let eligible static policy notes be revised visually. Preserve actual status/header observations with the tested Worker revision.