Skip to content

Instantly share code, notes, and snippets.

@simonw
Created June 20, 2026 17:51
Show Gist options
  • Select an option

  • Save simonw/264bd6b8a39fc34c91c9c867454c64b9 to your computer and use it in GitHub Desktop.

Select an option

Save simonw/264bd6b8a39fc34c91c9c867454c64b9 to your computer and use it in GitHub Desktop.

Build Cloudflare redirect resolver

Build a cloudflare worker app I can deploy using wrangler which provides an HTML form where I can paste a URL, it then follows redirects on that URL up to 10 times to report back the full redirect chain and the eventual location. It does this with HTTP GET that it cuts off as soon as headers have all come back.

24 previous messages

I’ll take a quick look at the repo shape first, then I’ll wire the Worker around whatever tooling is already there so it deploys cleanly with Wrangler.

Explored a list, ran 2 commands
Explored a list
  • Listed files
  • Ran pwd && rg --files -g '!*node_modules*' -g '!*.png' -g '!*.jpg' -g '!*.jpeg' -g '!*.gif'

  • Ran git status --short

This is a fresh repo, so I’m going to scaffold a small Wrangler Worker: TypeScript entrypoint, wrangler.toml, package scripts, and a README with deploy/local commands. The resolver will use manual redirect handling and cancel each response body immediately after headers are available.

Created 6 files
  • Wrote ./.gitignore (+5 -0)
  • Wrote ./README.md (+30 -0)
  • Wrote ./package.json (+17 -0)
  • Wrote ./src/index.ts (+604 -0)
  • Wrote ./tsconfig.json (+13 -0)
  • Wrote ./wrangler.toml (+6 -0)

The first pass is in place. I’m installing the declared dev tools now and will let TypeScript/Wrangler tell me if any Worker-specific types or runtime assumptions need tightening.

Ran a command
  • Ran npm install

Dependencies installed cleanly. Next I’m running the static check and a local Worker smoke test so the deployable path is actually exercised, not just sketched.

Ran 2 commands
  • Ran npm run check
  • Ran npm run deploy -- --dry-run

TypeScript passes and Wrangler’s dry-run bundle succeeds. I’m starting a local Worker and hitting both the HTML page and JSON endpoint with a known redirect so I can catch behavior issues in the actual runtime.

Ran 3 commands
  • Ran npm run dev -- --ip 127.0.0.1 --port 8787
  • Ran curl -sS -D - http://127.0.0.1:8787/ -o /tmp/redirect-resolver-page.html
  • Ran curl -sS 'http://127.0.0.1:8787/api/resolve?url=https%3A%2F%2Fhttpbin.org%2Fredirect%2F2'

The runtime smoke test is behaving as intended: the JSON endpoint followed two 302 hops from httpbin.org and stopped at the 200 final URL, with only headers used from each response. I’m doing one last pass over the files/status now.

Explored a search, ran a command
Explored a search
  • Searched for ./.git/* in .
  • Ran git status --short

One more small housekeeping pass: I want the manifest versions to line up with what npm actually installed, so future installs are boring and predictable.

Explored a file, ran a command
  • Ran node -e "const p=require('./package-lock.json'); console.log(p.packages['node_modules/wrangler'].version); console.log(p.packages['node_modules/@cloudflare/workers-types'].version); console.log(p.packages['node_modules/typescript'].version);"
Explored a file
  • Read ./package.json

The lockfile pulled in newer stable tool versions than the initial ranges, so I’m pinning the manifest ranges to those installed major/minor baselines before the final check.

Edited a file, ran a command
  • Wrote ./package.json (+3 -3)
  • Ran npm install

The manifest is synced and the dev server hot-reloaded. I’m rerunning the two verification commands after that package metadata change.

Ran 3 commands
  • Ran npm run check
  • Ran npm run deploy -- --dry-run
  • Ran curl -sS 'http://127.0.0.1:8787/api/resolve?url=https%3A%2F%2Fhttpbin.org%2Fredirect%2F2' | node -e "let s=''; process.stdin.on('data', d => s += d); process.stdin.on('end', () => { const r=JSON.parse(s); console.log([r.redirectCount, r.finalUrl, r.chain.length, r.error].join('\n')); });"

The main path is good, but I spotted one resilience gap while reviewing: a DNS/TLS/timeout failure mid-chain should render as a partial result instead of turning into a generic 500. I’m tightening that now so the UI and JSON endpoint still tell you where resolution stopped.

Edited a file
  • Wrote ./src/index.ts (+17 -1)

That error path is patched. I’m running the final verification set again against the current code.

Ran 4 commands
  • Ran npm run check
  • Ran npm run deploy -- --dry-run
  • Ran curl -sS 'http://127.0.0.1:8787/api/resolve?url=https%3A%2F%2Fhttpbin.org%2Fredirect%2F2' | node -e "let s=''; process.stdin.on('data', d => s += d); process.stdin.on('end', () => { const r=JSON.parse(s); console.log([r.redirectCount, r.finalUrl, r.chain.length, r.error].join('\n')); });"
  • Ran curl -sS -i 'http://127.0.0.1:8787/api/resolve?url=https%3A%2F%2Fnot-a-real-domain-for-redirect-resolver.invalid%2F'

The failure case now returns a structured 502 JSON payload instead of crashing, which is the right shape for bad domains or hosts that reject the request. I’m checking the final file set and then I’ll hand you the local URL plus deploy commands.

Ran 2 commands
  • Ran git status --short
  • Ran git diff --stat

Built the Wrangler-deployable Worker app.

Key files:

  • src/index.ts serves the HTML form and /api/resolve, follows up to 10 redirects with GET, uses redirect: "manual", and cancels each response body after headers arrive.
  • wrangler.toml configures the Worker.
  • README.md has local/dev/deploy notes.

Verification passed:

  • npm run check
  • npm run deploy -- --dry-run
  • Local smoke test followed https://httpbin.org/redirect/2 to https://httpbin.org/get with 2 redirects.

I left Wrangler dev running at http://127.0.0.1:8787. Deploy with:

npm run deploy

I want to try the new wrangler deploy --temporary command how would I run that myself?

4 previous messages

I’ll check the installed Wrangler help in this repo so I can give you the exact command shape it accepts here.

Ran a command, searched the web
  • Ran npx wrangler deploy --help
Searched the web
  • Searched the web for wrangler deploy --temporary Cloudflare Workers temporary deployments

Cloudflare’s docs say this flow is for Wrangler 4.102.0 or later, and this repo has 4.103.0 installed. I’m going to do a no-upload parser check with --dry-run so we know whether this local Wrangler accepts the hidden/new flag even though it didn’t show up in help.

Ran a command
  • Ran npx wrangler deploy --temporary --dry-run

Run it from the repo root:

cd /Users/simon/Dropbox/dev/cloudflare-redirect-resolver
npx wrangler deploy --temporary

Or using the existing npm script:

npm run deploy -- --temporary

Cloudflare’s docs say --temporary needs Wrangler 4.102.0 or later; this repo currently has 4.103.0, and I verified npx wrangler deploy --temporary --dry-run parses/builds successfully here. If you specifically want the temporary-account flow, Cloudflare recommends being logged out first:

npx wrangler logout
npx wrangler deploy --temporary

It should print a live workers.dev URL and a claim URL. The temporary deployment/account needs to be claimed within 60 minutes to keep it. Sources: Cloudflare Workers commands and Claim deployments.

Just call it Redirect Resolver not Cloudflare Redirect Resolver in the UI

6 previous messages

I’ll make the UI label change where the page title and heading are generated, then do a quick check for any remaining UI-facing occurrences.

Explored a file, a search
  • Searched for Cloudflare Redirect Resolver|Cloudflare-Redirect-Resolver in .
  • Read ./src/index.ts

I found the UI title constant; I’m changing just that, leaving the README/project metadata and User-Agent alone since you asked specifically about the UI.

Edited a file
  • Wrote ./src/index.ts (+1 -1)

The label is patched. I’ll type-check and curl the page title/heading from the running local Worker to make sure the browser should pick it up on refresh.

Ran 2 commands
  • Ran npm run check
  • Ran curl -sS 'http://127.0.0.1:8787/?url=http%3A%2F%2Fdatasette.io' | rg -n '<title>|<h1>'

Done. The UI now shows Redirect Resolver in both the browser title and main heading.

Verified with npm run check and a local page fetch from http://127.0.0.1:8787/?url=http%3A%2F%2Fdatasette.io.

is there a npx wrangler command to see if I am logged in or net

2 previous messages

I’ll ask the local Wrangler CLI so the answer matches the version in this project.

Ran a command
  • Ran npx wrangler whoami --help

Yes:

npx wrangler whoami

For a script-friendly check:

npx wrangler whoami --json

Wrangler says --json exits with a non-zero status if you are not authenticated, so this works too:

npx wrangler whoami --json >/dev/null && echo "logged in" || echo "not logged in"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment