Skip to content

Instantly share code, notes, and snippets.

@teyfix
Last active April 14, 2021 10:00
Show Gist options
  • Save teyfix/000f2d8bd3ef918bf6dfdac925a6882e to your computer and use it in GitHub Desktop.
Save teyfix/000f2d8bd3ef918bf6dfdac925a6882e to your computer and use it in GitHub Desktop.
Proxy script for CloudFlare workers

proxy worker

a simple script that proxies the content from another website to a path under your domain

DEMO

tadilatimkacpara.com/blog
FROM=https://blog.tadilatimkacpara.com
TO=/blog

how to use

creating the worker

  • create a worker from cloudflare dashboard
  • add FROM and TO environment variables ¹
  • paste the script to the worker source
  1. FROM stands for local path name (/lorem/ipsum) TO stands for remote url (https://example.com)

adding it to your domain

  • go to workers under your domain
  • add the worker with routes *.example.com/* and example.com/* ¹
  1. to be sure that worker will be availabe both on www.example.com and example.com ²

  2. you do not need to add two worker config (.examlpe.com/ and example.com/*) if you are redirecting example.com to www.example.com or www.example.com to example.com

const escapeURL = (url) => url.replace(/([\/])/g, "\\$1");
const escapeRegExp = (pattern) =>
pattern.replace(/([\[\\^$.|?*+(){}\/-])/g, "\\$1");
const proxy = ((source, target) => {
const targetPattern = new RegExp("(?<=[\"' ])" + escapeRegExp(target), "g");
const encodedTarget = encodeURIComponent(target);
const encodedTargetPattern = new RegExp(
"(?<==)" + escapeRegExp(encodedTarget),
"g"
);
const escapedTarget = escapeURL(target);
const escapedSource = escapeURL(source);
const escapedTargetPattern = new RegExp(
"(?<=[\"'])" + escapeRegExp(escapedTarget)
);
return (event) => {
let url = new URL(event.request.url);
const match = new RegExp("^" + source + "(/|$)").test(url.pathname);
if (match) {
const pathname = url.pathname.replace(source, "");
url = new URL(pathname + url.search + url.hash, target).href;
event.passThroughOnException();
}
event.respondWith(
fetch(url).then(async (response) => {
if (
match &&
response.headers.get("content-type").startsWith("text/html")
) {
const text = await response.text();
return new Response(
text
.replace(targetPattern, source)
.replace(encodedTargetPattern, source)
.replace(escapedTargetPattern, escapedSource),
response
);
}
return response;
})
);
};
})(FROM, TO);
addEventListener("fetch", proxy);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment