During my migration from Netlify to Cloudflare Workers Sites, one of the things I had to figure out was how to deal with redirects. Over the years, I’ve accumulated nearly 900 redirects from URL slug and permalink syntax changes. On Netlify, creating redirects was really simple – all that was required was a _redirects file containing all the redirects. Cloudflare Workers Sites doesn’t have support for redirects built in, so I had to create my own redirect handling.

In this article, I’ll show you how I’m redirecting URLs with Cloudflare Workers and Workers KV on a Hugo-generated static site.

Adding Redirects in index.js

Redirecting URLs with a Cloudflare Worker isn’t exactly a difficult thing to do. There are a variety of tutorials out there that detail how to perform redirects by specifying the source and destination URLs in the worker’s index.js file. In fact, Cloudflare has a code example for “Bulk Redirects”.

Here’s Cloudflare’s code example below.

const externalHostname = "examples.cloudflareworkers.com"

const redirectMap = new Map([
  ["/bulk1", "https://" + externalHostname + "/redirect2"],
  ["/bulk2", "https://" + externalHostname + "/redirect3"],
  ["/bulk3", "https://" + externalHostname + "/redirect4"],
  ["/bulk4", "https://google.com"],
])

async function handleRequest(request) {
  const requestURL = new URL(request.url)
  const path = requestURL.pathname.split("/redirect")[1]
  const location = redirectMap.get(path)
  if (location) {
	return Response.redirect(location, 301)
  }
  // If request not in map, return the original request
  return fetch(request)
}

addEventListener("fetch", async event => {
  event.respondWith(handleRequest(event.request))
})

As you can see, the source and destination URLs are provided in this format.

["/bulk1", "https://" + externalHostname + "/redirect2"]

Since my site has nearly 900 redirects, adding all of them to my Worker’s index.js file didn’t seem like the best way of doing things.

Adding Redirects to Workers KV

After a little coffee and brainstorming, I realized Workers KV (the same database that stores my Hugo site) could also be used for storing redirects. Since Workers KV is a key-value database, the “key” can be used as the redirect source and the “value” can be used for redirect destination. To get started, I created a new Workers KV namespace in the Cloudflare dashboard.

Create a Cloudflare Workers KV namespace for storing redirects.
Create a Cloudflare Workers KV namespace for storing redirects.

I named my redirects namespace __brianli-com-workers_redirects. As you can see, each namespace has an ID (blurred in the screenshot below).

After creating the namespace, I added the line below to my wrangler.toml file for my site (be sure to replace [namespace_id] with the ID of your KV namespace. This line binds the KV namespace to the REDIRECTS variable, which can be used in the index.js file for the Cloudflare worker.

kv_namespaces = [ { binding = "REDIRECTS", id = "[namespace_id]" } ]

Next, I added the code below to my index.js file. This JavaScript queries REDIRECTS (binding to the KV namespace) for the URL slug (URL pathname with first and last forward slashes removed with replace(/^\/|\/$/g, '')). The worker then creates a new HTTP 301 response with the destination URL specified in the Location header.

let redirect = await REDIRECTS.get(url.pathname.replace(/^\/|\/$/g, ''));

if (redirect) {
	// ... return a HTTP 301 response.
	return new Response(null, {
		'status': 301,
		'headers': {
			'Location': '/' + redirect + '/',
			'X-Redirect-By': 'cloudflare'
		}
	});
}

Finally, redirects can be added in the format below.

Key: some-old-url-slug
Value: some-new-url-slug

Redirects can be added in the Cloudflare dashboard, or programmatically via Wrangler or the Cloudflare REST API. If you’re technically capable, I’d recommend adding redirects programmatically. To import my existing ~900 redirects, I created a simple Bash script with a list of wrangler commands like the one below. After the script finished executing, I tested a few redirects and everything appeared to be working well.

wrangler kv:key put --binding= [--namespace-id=] "some-old-url-slug" "some-new-url-slug"

If your website or app is hosted on Cloudflare Workers Sites, and you’re looking for a way to implement redirects, I’d recommend storing the redirects in Workers KV. With this method, you can keep your index.js uncluttered, which ultimately makes code deploys faster and more streamlined.

If you have any questions about how to bulk redirect URLs with Cloudflare Workers and Workers KV, feel free to send me an email or reach out on Twitter!