Proxy pass with Cloudflare workers

Proxy pass with Cloudflare workers

This is sample POC for the problem below.

Problem

Screenshot-2020-10-10-at-11.51.15-AM

For a website,

  • if http:// and/or www is used, it should be redirected to https://example.com
  • for /blog, worker should proxy pass to https://blog.example.com
  • for /pricing, proxy pass to https://pricing.example.com

Proxy pass: It means that request is internally routed to a different server or a website but client will see it as coming from same website. i.e. client won't see any url changes.

Solution with cloudflare worker

For the sake of this example, I'm using innodollar.com

Here are the DNS records: Make sure we've a DNS record for www as CNAME, and proxy is enabled.

Screenshot-2020-10-10-at-11.46.35-PM

Next up, enable the flag of "Always use https" under SSL/TLS, Edge Certificates tab.

Screenshot-2020-10-10-at-11.47.59-PM

Let's add a page rule to remove "www"

Notice * and $1 They're important to keep the requests intact while changing the root url.

Screenshot-2020-10-11-at-12.00.23-AM

Now, let's handle special cases of /blog and /pricing. Since we don't want clients to notice we're loading a different website, we've to make use of workers instead of forwarding rules.

Let's create a worker:

Briefly, the worker code below accepts /blog and /pricing urls and directs them to acsrujan.net/blog and example.com/pricing respectively.

var host = 'https://innodollar.com/'
addEventListener('fetch', event => {
  var url = new URL(event.request.url);
    if (url.pathname.startsWith('/pricing')) {
        proxyExample(event.request, url, event)
    } else if (url.pathname.startsWith('/blog')) {
        proxyAcsrujan(event.request, url, event)
    } else {
        console.log("something unhandled")
    }
})
async function proxyExample(request, url, event) {
    let hostUrl = host
    const originUrl = url.toString().replace(
    hostUrl,
    'https://example.com/');
    event.respondWith(fetch(originUrl));
}
async function proxyAcsrujan(request, url, event) {
    const originUrl = url.toString().replace(
    host,
    'https://acsrujan.net/');
    event.respondWith(fetch(originUrl));
}

Let's add the above worker using Manage workers tab below. Once done, we come back to this page to add routes on which worker is to be triggered, as shown. Notice the * in both routes

Screenshot-2020-10-11-at-12.52.05-AM

Let's test

In order to test, we can quickly do a curl request and find out if it all worked out.
Ex (output redacted for brevity):

curl -i http://www.innodollar.com/blog

HTTP/1.1 301 Moved Permanently
Date: Sat, 10 Oct 2020 19:26:38 GMT
Location: https://innodollar.com/blog

Expected behaviour:
http://www.innodollar.com/ and https://www.innodollar.com/ should be redirected to https://innodollar.com

/blog and /pricing in any of the above domains should also go to https://innodollar.com/blog and https://innodollar.com/pricing

Benefits:

And now we've cloudflare workers for proxy pass. The benefit of using worker here, is it is invoked only when users visit specified routes, unlike traditional nginx server which will be hit for every request.

P.S.: Drop me a message on twitter @acsrujan or [email protected] for any queries. :)