用于重定向的通配符域和路径名正则表达式

Wildcard domain and pathname regex for redirection

我正在尝试让批量重定向在 cloudflare workers 中工作。这是一个包含 tofrom url 的对象数组,有些将是跨域的。

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

我想尊重通配符并尝试根据 url 的路径名进行重定向。

这是我的尝试,但这只是针对固定路径名,而不是跨域。在 workers playground 编辑器中测试跨域有点困难。

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

如何更改此代码以使其支持使用通配符的重定向?通配符很可能总是在最后,一些路径名不会有通配符,它​​不会总是 /product 而是重定向对象中的任何路径名。

回答后更新:

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

结果:

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

您可以使用 Array#split() 将整个 URL 匹配到您的重定向,同时获取通配符“之后”的部分:

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

对于不匹配此重定向的 URL,结果将是 undefined,因此:

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