Home > Software engineering >  Wildcard domain and pathname regex for redirection
Wildcard domain and pathname regex for redirection

Time:01-22

I'm trying to get batch redirection working in cloudflare workers. Here's an array of objects with to and from urls, some will be cross domain.

const redirects = [
  {
    "from": "https://some.domain.tld/product/*",
    "to": "https://another.domain.tld/product/*"
  },
]

I'd like to respect the wildcards and try to redirect based on the pathname of the url.

here's my attempt, but this is just for fixed pathnames and not cross-domain. It's kind of hard to test for cross-domain in the workers playground editor.

async function handleRequest(request) {
  const  url = new URL(request.url)
  const host = url.hostname;
  const path = url.pathname;
  const queryStrings = url.search;

  const location = redirects.find(r => {
      return r.from.includes(path);
  });
  
  if (location) {
   return Response.redirect('https://'   host   location.to   queryStrings, 301)
  }
  return fetch(request)
}

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

How can I change this code so it respects redirects with wildcards? Wildcards will most likely always be at the end, some pathnames will not have wildcards, and it will not always be /product but any pathname that's in the redirect object.

Updated after answer:

const redirects = [
  {
    "from": "https://red.domain.com/product-1/*",
    "to": "https://blue.domain.com/product-1/*"
  },
]

async function handleRequest(request) {
    const url = 'https://red.domain.com/product-1/fees';
    const location = redirects.reduce((loc, r) => {
      let match = url.split(r.from.replace("*", "")[1]);
      if (match) return r.to.replace("*", "")   match;
  }, "");
  if (location) {
   return Response.redirect(location, 301)
  }
  return fetch(request)
}

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

result:

https://blue.domain.com/product-1/h,,ps://red.domain.com/produc,-1/fees

CodePudding user response:

You can match the whole URL to your redirects using Array#split(), while getting the part "after" the wildcard back:

console.log(
"https://some.domain.tld/product/foo/bar/baz?test=baf".split("https://some.domain.tld/product/")[1]
)

For URLs that don't match this redirect, the result will be undefined, so:

const redirects = [
  {
    "from": "https://some.domain.tld/product/*",
    "to": "https://another.domain.tld/product/*"
  },
]


async function handleRequest(request) {
  const {url} = request;

  const location = redirects.reduce((loc, r) => {
    let match = url.split(r.from.replace("*","")[1]; // remove wildcard * for matching
    if(match) return r.to.replace("*","")   match;
  },"")
  
  if (location) {
   return Response.redirect(location, 301)
  }
  return fetch(request)
}

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