Search code examples
cloudflarecloudflare-workers

Forward request from one domain to another without changing the URL in browser


i am trying to add a worker which will redirect/forward the request from https://test1.com to https://test2.com

const redirectHttpCode = 301
const targetUrl = "https://test2.com"
addEventListener('fetch', event => {
  event.respondWith(handleRequest(event.request))
})
async function handleRequest(request) {
  if (targetUrl) {
    return Response.redirect(targetUrl, redirectHttpCode)
  }
  return fetch(request)
}

the route configured as *test1.com/* to above worker

with this worker if i try to access https://test1.com it redirects the request to https://test2.com and changes the URL in browser with status code 301 as expected.

is it possible to forward/redirect the request from https://test1.com to https://test2.com without changing the URL in the browser or User getting to know there is a redirection happened?


Solution

  • As shown in the example Respond with another site, you need to call respondWith with the answer of the final website. Given respondWith can handle either a Response or a promise that will eventually unfold into a response, the simplest case is returning a fetch call:

    async function handleEvent(event) {
      event.respondWith(fetch('https://www.test2.com'))
    }
    

    In which case you would be connecting two streams, without awaiting for test2 whatsoever.

    When the use case involves modifying the actual response (as in the example: Alter Headers), you'll need to await the outcome of fetch, and perform any modification on a clone of it, because the former is inmutable.

    async function handleRequest(request) {
      const response = await fetch('https://www.test2.com'),
            modifiedResponse = new Response(response.body, response);
    
      modifiedResponse.headers.set('Access-Control-Allow-Origin', '*')
      return modifiedResponse;
    }
    
    async function handleEvent(event) {
      event.respondWith(handleRequest(event.request))
    }
    

    Errata 2022-02-21

    The original answer said you could clone the response to get one with mutable headers. This is wrong. Doing

        modifiedResponse = response.clone();
    

    Gets you a clone whose headers are just as inmutable as the original. The right way is to use the Response constructor

        modifiedResponse = new Response(response.body, response);