Using Cloudflare workers to redirect multiple URLS

Hi Team,

I was wondering if it was possible to run 1 Cloudflare worker to redirect multiple URL. Example a site has migrated to a new website plaform which is https://example.com.au/pages/about-us and new site is https://example.com.au/about-us and we want to remove /pages is just one example but there is many others need to do example redirect /help to another platform https://example2.net/help etc

any way can create a CF worker to handle multiple redirects in a single worker? Any one have any good examples to use?

I am aware of redirect in bulk tool and would be great however free plan is limited to 20 and I need 45 redirects.

Hi @ace8

Sure, it is possible to use a worker as a redirector.

If you want to rewrite specific /pages/<some-page> to /<some-page>, you could add a condition such as

const url = new URL(request.url)

if (url.pathname.startsWith('/pages/')) {
  url.pathname = url.pathname.replace('/pages/', '/')
}
else if (something === somethingElse) {
// do something else
}
// and so on

return new Response(`Redirecting to: ${url.href}`, {
  status: 301,
  headers: {
    Location: url.href
  }
})

Hi @the thanks for that. I was reading this: Bulk redirects · Cloudflare Workers docs

and was wondering could i modify this

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))
})

But instead mdify the top part of the code to look like this instead wondering if this will work

// const externalHostname = "examples.cloudflareworkers.com"  - remark this out

const redirectMap = new Map([
  ["/bulk1", "https://example.com.au/redirect2"],
  ["/bulk2", "https://example.com.au/redirect3"],
  ["/bulk3", "https://example.com.au/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))
})

Do you know if that could work ? And would allow a bu

Modifying that script would work.

You could manually add the redirects like

[ "/pages/about-us", "https://example.com.au/about-us" ],
[ "/pages/another-page", "https://example.com.au/new-location" ]

and if there is a match redirect otherwise fetch the original request. This wouldn’t need the splitting of the pathname meaning

const location = redirectMap.get(path)
// would change to
const location = redirectMap.get(requestURL.pathname)

Or if there are many pages, implement the checking of the pathname I earlier suggested, or combination of both.

So you are suggesting this would work:

const redirectMap = new Map([
  ["/bulk1", "https://example.com.au/redirect2"],
  ["/bulk2", "https://example.com.au/redirect3"],
  ["/bulk3", "https://example.com.au/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(requestURL.pathname)
  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))
})

Correct?

If you only want to redirect a URL with a pathname beginning with /pages/ you would first check if the request URL contains /pages/ something like

const { pathname } = new URL(request.url)
if (pathname.startsWith('/pages/') { /* more here */ }

Then inside the if remove /pages/ from the pathname and check the existence of a redirect in the map something like

const location = redirectMap.get(pathname.slice(7))
if (location)
  return Response.redirect(location, 301)

Otherwise the request passes through to fetch.

@the your a weapon love your work man! Thanks.

Quick question its all working perfectly! One last thing however though is any urls not mentioned in the script basically fall back to the original request as per here:

 // If request not in map, return the original request
  return fetch(request)

My question is how could i replace that if none of the redirects match it will redirect everything else to https://xxxx.com for example?

Simply change the return fetch(request) to return Response.redirect('https://example.com', 301).

If you want more fine grained control over headers, instead of Response.redirect use

return new Response(null, {
  status: 301, // or 301, 307, 308
  headers: {
    Location: 'https://example.com',
    // other custom headers as required.
  }
})

If you wish check out this script

@the you nailed what a legend! thanks mate!