fix html rewriting and add header rewriting

This commit is contained in:
Avad3 2024-05-06 19:00:10 -04:00
parent b8ee2ef53e
commit 2002eab48c
6 changed files with 80 additions and 11 deletions

View file

@ -20,7 +20,6 @@
"no-useless-return": "error",
"no-shadow": "error",
"prefer-const": "warn",
"prefer-reflect": "warn",
"no-unreachable": "warn",
"no-undef": "off"
}

View file

@ -2,6 +2,7 @@ import { encodeUrl, decodeUrl } from "./rewriters/url";
import { rewriteCss } from "./rewriters/css";
import { rewriteHtml, rewriteSrcset } from "./rewriters/html";
import { rewriteJs } from "./rewriters/js";
import { rewriteHeaders } from "./rewriters/headers";
const bundle = {
rewriters: {
@ -11,7 +12,8 @@ const bundle = {
rewriteCss,
rewriteHtml,
rewriteSrcset,
rewriteJs
rewriteJs,
rewriteHeaders
}
}

View file

@ -0,0 +1,50 @@
import { encodeUrl } from "./url";
const cspHeaders = [
"cross-origin-embedder-policy",
"cross-origin-opener-policy",
"cross-origin-resource-policy",
"content-security-policy",
"content-security-policy-report-only",
"expect-ct",
"feature-policy",
"origin-isolation",
"strict-transport-security",
"upgrade-insecure-requests",
"x-content-type-options",
"x-download-options",
"x-frame-options",
"x-permitted-cross-domain-policies",
"x-powered-by",
"x-xss-protection",
];
const urlHeaders = [
"location",
"content-location",
"referer"
];
export function rewriteHeaders(headers: Headers, origin?: string) {
cspHeaders.forEach((header) => {
if (headers.has(header)) {
headers.delete(header);
}
});
urlHeaders.forEach((header) => {
if (headers.has(header)) {
headers.set(header, encodeUrl(headers.get(header), origin));
}
});
if (headers.has("link")) {
let link = headers.get("link");
link = link.replace(/<(.*?)>/g, (match, g1) => {
return `<${encodeUrl(g1, origin)}>`;
});
headers.set("link", link);
}
}

View file

@ -4,6 +4,7 @@ import { hasAttrib, getAttributeValue } from "domutils";
import render from "dom-serializer";
import { encodeUrl } from "./url";
import { rewriteCss } from "./css";
import { rewriteJs } from "./js";
// html nodes to rewrite
// meta
@ -18,9 +19,10 @@ export function rewriteHtml(html: string, origin?: string) {
return render(traverseParsedHtml(handler.root, origin));
}
// typescript error hell
// the code still works but the types provided from domhandler are shit
function traverseParsedHtml(node: any, origin?: string) {
function traverseParsedHtml(node, origin?: string) {
// apparently nonce is a global attribute so i'll just delete it at the beginning of the file
delete node.attribs.nonce;
if (node.name === "a" && hasAttrib(node, "href")) {
node.attribs.href = encodeUrl(node.attribs.href, origin);
} else if (node.name === "iframe") {
@ -31,12 +33,25 @@ function traverseParsedHtml(node: any, origin?: string) {
if (hasAttrib(node, "srcdoc")) {
node.attribs.srcdoc = rewriteHtml(node.attribs.srcdoc, origin);
}
if (hasAttrib(node, "csp")) {
delete node.attribs.csp;
}
} else if (node.name === "link") {
delete node.attribs.integrity;
node.attribs.href = encodeUrl(node.attribs.href, origin);
if (hasAttrib(node, "imagesrcset")) {
node.attribs.imagesrcset = rewriteSrcset(node.attribs.imagesrcset);
}
console.log(node.attribs.href)
} else if (node.name === "style") {
node.children[0].data = rewriteCss(node.children[0].data, origin);
} else if (node.name === "script") {
delete node.attribs.integrity;
if (hasAttrib(node, "type") && /(application|text)\/javascript|importmap/.test(getAttributeValue(node, "type"))) {
if (hasAttrib(node, "src")) {
node.attribs.src = encodeUrl(node.attribs.src, origin);
@ -44,7 +59,7 @@ function traverseParsedHtml(node: any, origin?: string) {
}
}
// implement js rewriting when done
node.children[0].data = rewriteJs(node.children[0].data, origin);
} else if (node.name === "img" && hasAttrib(node, "src")) {
if (hasAttrib(node, "src")) {
node.attribs.src = encodeUrl(node.attribs.src, origin);

View file

@ -1,3 +1,5 @@
import { rewriteJs } from "./js";
function canParseUrl(url: string, origin?: string) {
if (URL.canParse) {
console.log(URL.canParse(url, origin) + "\n" + url + "\n" + origin);
@ -21,14 +23,11 @@ export function encodeUrl(url: string, origin?: string) {
// }
if (url.startsWith("javascript:")) {
// implement when js rewriting is done
return url;
return "javascript:" + rewriteJs(url.slice("javascript:".length));
} else if (/^(#|mailto|about|data)/.test(url)) {
return url;
} else if (canParseUrl(url, origin)) {
console.log(self.__scramjet$config.prefix + self.__scramjet$config.codec.encode(new URL(url, origin).href));
return self.__scramjet$config.prefix + self.__scramjet$config.codec.encode(new URL(url, origin).href);
return location.origin + self.__scramjet$config.prefix + self.__scramjet$config.codec.encode(new URL(url, origin).href);
}
}

View file

@ -19,6 +19,8 @@ self.ScramjetServiceWorker = class ScramjetServiceWorker {
async fetch(event: FetchEvent) {
const url = new URL(self.__scramjet$bundle.rewriters.url.decodeUrl(event.request.url));
self.__scramjet$bundle.rewriters.rewriteHeaders(event.request.headers)
// implement header rewriting later
const response = await this.client.fetch(url, {
method: event.request.method,
@ -26,6 +28,8 @@ self.ScramjetServiceWorker = class ScramjetServiceWorker {
headers: event.request.headers
});
self.__scramjet$bundle.rewriters.rewriteHeaders(response.headers);
let responseBody;
if (event.request.destination === "document") {