Skip to content

Instantly share code, notes, and snippets.

@rfletcher
Last active February 21, 2021 15:41
Show Gist options
  • Save rfletcher/f5dd422991e6cac65c0135f9dec614f8 to your computer and use it in GitHub Desktop.
Save rfletcher/f5dd422991e6cac65c0135f9dec614f8 to your computer and use it in GitHub Desktop.
/**
* A CloudFlare Worker which proxies an RSS feed, ensuring all <link/> values are secure URLs.
*
* Note: Works for my use case, but this needs more error checking before using widely.
*
* Usage: https://<yourworker>.workers.dev/https://example.com/feed.rss
*/
addEventListener("fetch", event => {
event.respondWith(handleRequest(event.request))
})
class ElementHandler {
constructor() {
this.textBuffer = "";
this.isLink = false;
}
element(element) {
this.isLink = element.tagName.toLowerCase() == "link";
}
comments(comment) {}
text(text) {
if (this.isLink) {
this.textBuffer += text.text;
if (!text.lastInTextNode) {
text.remove();
} else {
let url = new URL(this.textBuffer);
url.protocol = 'https:';
text.replace(url.toString());
this.textBuffer = "";
}
}
}
}
// really only need to match "link" here, but the `text()` method is only called with "*".
const rewriter = new HTMLRewriter().on("*", new ElementHandler());
async function handleRequest(request) {
// using a query param for input would be simpler, but my
// feed reader didn't like it. resort to path instead.
const { pathname } = new URL(request.url);
// strip the leading '/'
let url = pathname.substr(1);
// URL-decode if necessary
if (url.match(/%[a-f0-9]{2}/i)) {
url = decodeURIComponent(url);
}
// restore '//', which was collapsed to '/'
url = url.replace(/^(https?:)\/([^/])/i, "$1//$2");
const response = await fetch(url);
return rewriter.transform(response);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment