[workers-shared] `_redirects` targets like `https://host?query` and `https://host#hash` get a trailing slash appended after the query/fragment
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 72/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- typescript, wasm
Research direction
Start with URL_REGEX and extractPathname in packages/workers-shared/utils/configuration/validateURL.ts, then trace how parseRedirects in parseRedirects.ts passes the target through validateUrl. Run the three-line parseRedirects snippet from the issue to reproduce. Done when https://example.com?utm=1 and https://example.com#section keep their query or fragment without a trailing /, while https://example.com/?utm=1 still parses as before.
Written by the indexing model from the issue text.
Description
What versions & operating system are you using?
[email protected], main (81e56dd), Node.js v26.13.0, Linux x64
Please provide a link to a minimal reproduction
https://gist.github.com/trackoor/a6e485cf5e6727fa1e3aa1d0313d43ee
Describe the Bug
In packages/workers-shared/utils/configuration/validateURL.ts, validateUrl splits absolute URLs with URL_REGEX = /^https:\/\/+(?<host>[^/]+)\/?(?<path>.*)/. When a _redirects target is an absolute URL with a query string or fragment and no / before it (such as https://example.com?utm=1 or https://example.com#section), (?<host>[^/]+) captures the query string or fragment as part of host, and extractPathname("") appends / after it.
Steps to reproduce with [email protected]:
mkdir -p public
cat > public/_redirects << 'EOF'
/a https://example.com?utm=1
/b https://example.com#section
/c https://example.com/?utm=1
EOF
cat > wrangler.json << 'EOF'
{"name":"repro","compatibility_date":"2026-01-01","assets":{"directory":"./public"}}
EOF
node -e '
const { unstable_dev } = require("wrangler");
(async () => {
const worker = await unstable_dev(undefined, { config: "wrangler.json", experimental: { disableExperimentalWarning: true } });
for (const p of ["/a", "/b", "/c"]) {
const res = await worker.fetch("http://localhost" + p, { redirect: "manual" });
console.log(p, res.status, res.headers.get("location"));
}
await worker.stop();
})();
'
Also directly via parseRedirects on main (81e56dd):
import { parseRedirects } from "./packages/workers-shared/utils/configuration/parseRedirects";
for (const line of [
"/a https://example.com?utm=1",
"/b https://example.com#section",
"/c https://example.com/?utm=1",
]) {
console.log(line, "->", parseRedirects(line).rules.map((r) => r.to));
}
// /a https://example.com?utm=1 -> [ 'https://example.com?utm=1/' ]
// /b https://example.com#section -> [ 'https://example.com#section/' ]
// /c https://example.com/?utm=1 -> [ 'https://example.com/?utm=1' ]
Actual output from unstable_dev:
/a 302 https://example.com/?utm=1/
/b 302 https://example.com/#section/
/c 302 https://example.com/?utm=1
Expected output:
/a 302 https://example.com/?utm=1
/b 302 https://example.com/#section
/c 302 https://example.com/?utm=1
According to the WHATWG URL Standard, a host ends at /, ?, or #, so https://example.com?utm=1 and https://example.com/?utm=1 have the same host (example.com), pathname (/), and query (?utm=1).
Please provide any relevant error logs
No error or warning is logged ([wrangler:info] ✨ Parsed 3 valid redirect rules.).
Credit: https://ucsbplse.github.io/
- Dominant language
- TypeScript
- Stars
- 4.7k
- Forks
- 1.6k
- Avg merge
- 1d 23h
- Merged PRs (30d)
- 268
Getting set up
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from cloudflare/workers-sdk
-
Miniflare email() handler message has no canBeForwarded property in local devPossibly taken @mindulle claimed this 4 days ago. Openbug package:miniflare product:email
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
cloudflare/workers-sdk#16790 · 3 comments ·
Maintainers usually reply within 1 day
-
Miniflare send_email accepts an EmailAddress without `name`, then drops it from the Local ExplorerMay be free again A pull request for this issue was closed without being merged. Openbug package:miniflare product:email
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
cloudflare/workers-sdk#16788 · 2 comments ·
Maintainers usually reply within 1 day
-
[workers-auth] Reject misleading Cloudflare Access 302 redirectsMay be free again @akhil9tiet claimed this 7 days ago, and no pull request is open. Openbug package:workers-auth
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
cloudflare/workers-sdk#16755 · 2 comments ·
Maintainers usually reply within 1 day
-
wrangler preview: require an explicit previews block only when needed (empty {} should be implied)Openpackage:wrangler product:previews
Difficulty 2/5 1-3 hours Newbie friendliness 67/100
cloudflare/workers-sdk#16754 · 1 comment ·
Maintainers usually reply within 1 day
-
bug feature:workers-assets package:deploy-helpers package:wrangler
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
cloudflare/workers-sdk#16713 · 1 comment ·
Maintainers usually reply within 1 day
All issues in cloudflare/workers-sdk
Similar issues
-
Wallet functions throws TypeError when the wallet has no account IDPossibly taken @Medhansh-741 claimed this today. Openbug
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
hiero-ledger/hiero-sdk-js#4781 · 1 comment ·
Maintainers usually reply within 1 day
-
good first issue
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
dataforgoodfr/mediterranean-rescue#91 ·
Maintainers usually reply within 1 day
-
transformer-directives: `@apply` drops a utility whose CSS is a substring of an earlier one'sPossibly taken A pull request linked to this issue is open or already merged. Open
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
Maintainers usually reply within 1 day
-
Add: KRT TVOpenapproved check:passed streams:add
Difficulty 1/5 Under an hour Newbie friendliness 65/100
iptv-org/iptv#58647 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
milind-soni/OpenMausBot#5829 ·
Maintainers usually reply within 1 day