HOW TO: Use Cloudflare to reverse proxy a subdirectory

October 19, 2021

What is this for?
You have a requirement to serve a complete site through a "subdirectory" (ie. /news or /blog) without being able to move it "physically" to a subdirectory on your root domain's server.

Head to the Workers page in your Cloudflare account, create a new Worker and add the following snippet into the Script box:

const LIVE_DOMAIN = '403page.com'
const PROXY_FROM_DOMAIN = '403.news.site.com'
const SUBDIR_PATH = '/news'

// Optional additional proxy path
const ADDITIONAL_PATH = '/images'

addEventListener("fetch", event => {
    var f_url = new URL(event.request.url);
    if (f_url.pathname.startsWith(SUBDIR_PATH)||f_url.pathname.startsWith (ADDITIONAL_PATH)) {
    handleSubdir(event, f_url);
    event.respondWith(handleSubdir(event.request));
  } else {
    return;
  }
});

async function handleSubdir(request) {
    var trueSourceURL = new URL(request.url);
    trueSourceURL.hostname = PROXY_FROM_DOMAIN;
    return fetch(trueSourceURL, request, { cf: { resolveOverride: LIVE_DOMAIN } })
}

Add the Worker to the route of your live domain (ie. domain.com/*)

You'll also want to modify your home and siteurl values so they can be set by WordPress dynamically. You can do this by adding these lines in your wp-config.php (again, on the source install):

define('WP_SITEURL', 'https://' . $_SERVER['SERVER_NAME']);
define('WP_HOME', 'https://' . $_SERVER['SERVER_NAME']);

Swap the slug or "subdirectory" (in this case it's news), as well as your desired user-facing domain (in this case it's https://403.ie/news) and the source domain (in this case it's https://403.NEWS.SITE.COM.

Once you click Save, your subdirectory will now serve the site from the source (visiting https://403.ie/news will show you the content from https://403.news.site.com).

(ALTERNATIVE) LEGACY VERSION

addEventListener('fetch', event => {
  var url = new URL(event.request.url);
  if (url.pathname.startsWith('/news/') || url.pathname === '/news') {
    handleBlog(event, url);
  } else {
    event.respondWith(fetch(event.request));
  }
})

async function handleBlog(event, url) {
  var originUrl = url.toString().replace(
    'https://403.ie/news',
   'https://403.NEWS.SITE.COM');
  event.respondWith(fetch(originUrl)); 
}

NOTE: Cloudflare allows for up to 100,000 worker requests per 24 hours and 5,000 requests per 10 minutes on a free plan. Check out their pricing after that here.