mirror of
https://github.com/MercuryWorkshop/scramjet.git
synced 2025-05-14 15:00:01 -04:00
fix html rewriting and add header rewriting
This commit is contained in:
parent
b8ee2ef53e
commit
2002eab48c
6 changed files with 80 additions and 11 deletions
|
@ -20,7 +20,6 @@
|
||||||
"no-useless-return": "error",
|
"no-useless-return": "error",
|
||||||
"no-shadow": "error",
|
"no-shadow": "error",
|
||||||
"prefer-const": "warn",
|
"prefer-const": "warn",
|
||||||
"prefer-reflect": "warn",
|
|
||||||
"no-unreachable": "warn",
|
"no-unreachable": "warn",
|
||||||
"no-undef": "off"
|
"no-undef": "off"
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ import { encodeUrl, decodeUrl } from "./rewriters/url";
|
||||||
import { rewriteCss } from "./rewriters/css";
|
import { rewriteCss } from "./rewriters/css";
|
||||||
import { rewriteHtml, rewriteSrcset } from "./rewriters/html";
|
import { rewriteHtml, rewriteSrcset } from "./rewriters/html";
|
||||||
import { rewriteJs } from "./rewriters/js";
|
import { rewriteJs } from "./rewriters/js";
|
||||||
|
import { rewriteHeaders } from "./rewriters/headers";
|
||||||
|
|
||||||
const bundle = {
|
const bundle = {
|
||||||
rewriters: {
|
rewriters: {
|
||||||
|
@ -11,7 +12,8 @@ const bundle = {
|
||||||
rewriteCss,
|
rewriteCss,
|
||||||
rewriteHtml,
|
rewriteHtml,
|
||||||
rewriteSrcset,
|
rewriteSrcset,
|
||||||
rewriteJs
|
rewriteJs,
|
||||||
|
rewriteHeaders
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ import { hasAttrib, getAttributeValue } from "domutils";
|
||||||
import render from "dom-serializer";
|
import render from "dom-serializer";
|
||||||
import { encodeUrl } from "./url";
|
import { encodeUrl } from "./url";
|
||||||
import { rewriteCss } from "./css";
|
import { rewriteCss } from "./css";
|
||||||
|
import { rewriteJs } from "./js";
|
||||||
|
|
||||||
// html nodes to rewrite
|
// html nodes to rewrite
|
||||||
// meta
|
// meta
|
||||||
|
@ -18,9 +19,10 @@ export function rewriteHtml(html: string, origin?: string) {
|
||||||
return render(traverseParsedHtml(handler.root, origin));
|
return render(traverseParsedHtml(handler.root, origin));
|
||||||
}
|
}
|
||||||
|
|
||||||
// typescript error hell
|
function traverseParsedHtml(node, origin?: string) {
|
||||||
// the code still works but the types provided from domhandler are shit
|
// apparently nonce is a global attribute so i'll just delete it at the beginning of the file
|
||||||
function traverseParsedHtml(node: any, origin?: string) {
|
delete node.attribs.nonce;
|
||||||
|
|
||||||
if (node.name === "a" && hasAttrib(node, "href")) {
|
if (node.name === "a" && hasAttrib(node, "href")) {
|
||||||
node.attribs.href = encodeUrl(node.attribs.href, origin);
|
node.attribs.href = encodeUrl(node.attribs.href, origin);
|
||||||
} else if (node.name === "iframe") {
|
} else if (node.name === "iframe") {
|
||||||
|
@ -31,12 +33,25 @@ function traverseParsedHtml(node: any, origin?: string) {
|
||||||
if (hasAttrib(node, "srcdoc")) {
|
if (hasAttrib(node, "srcdoc")) {
|
||||||
node.attribs.srcdoc = rewriteHtml(node.attribs.srcdoc, origin);
|
node.attribs.srcdoc = rewriteHtml(node.attribs.srcdoc, origin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hasAttrib(node, "csp")) {
|
||||||
|
delete node.attribs.csp;
|
||||||
|
}
|
||||||
} else if (node.name === "link") {
|
} else if (node.name === "link") {
|
||||||
|
delete node.attribs.integrity;
|
||||||
|
|
||||||
node.attribs.href = encodeUrl(node.attribs.href, origin);
|
node.attribs.href = encodeUrl(node.attribs.href, origin);
|
||||||
|
|
||||||
|
if (hasAttrib(node, "imagesrcset")) {
|
||||||
|
node.attribs.imagesrcset = rewriteSrcset(node.attribs.imagesrcset);
|
||||||
|
}
|
||||||
|
|
||||||
console.log(node.attribs.href)
|
console.log(node.attribs.href)
|
||||||
} else if (node.name === "style") {
|
} else if (node.name === "style") {
|
||||||
node.children[0].data = rewriteCss(node.children[0].data, origin);
|
node.children[0].data = rewriteCss(node.children[0].data, origin);
|
||||||
} else if (node.name === "script") {
|
} else if (node.name === "script") {
|
||||||
|
delete node.attribs.integrity;
|
||||||
|
|
||||||
if (hasAttrib(node, "type") && /(application|text)\/javascript|importmap/.test(getAttributeValue(node, "type"))) {
|
if (hasAttrib(node, "type") && /(application|text)\/javascript|importmap/.test(getAttributeValue(node, "type"))) {
|
||||||
if (hasAttrib(node, "src")) {
|
if (hasAttrib(node, "src")) {
|
||||||
node.attribs.src = encodeUrl(node.attribs.src, origin);
|
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")) {
|
} else if (node.name === "img" && hasAttrib(node, "src")) {
|
||||||
if (hasAttrib(node, "src")) {
|
if (hasAttrib(node, "src")) {
|
||||||
node.attribs.src = encodeUrl(node.attribs.src, origin);
|
node.attribs.src = encodeUrl(node.attribs.src, origin);
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { rewriteJs } from "./js";
|
||||||
|
|
||||||
function canParseUrl(url: string, origin?: string) {
|
function canParseUrl(url: string, origin?: string) {
|
||||||
if (URL.canParse) {
|
if (URL.canParse) {
|
||||||
console.log(URL.canParse(url, origin) + "\n" + url + "\n" + origin);
|
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:")) {
|
if (url.startsWith("javascript:")) {
|
||||||
// implement when js rewriting is done
|
return "javascript:" + rewriteJs(url.slice("javascript:".length));
|
||||||
return url;
|
|
||||||
} else if (/^(#|mailto|about|data)/.test(url)) {
|
} else if (/^(#|mailto|about|data)/.test(url)) {
|
||||||
return url;
|
return url;
|
||||||
} else if (canParseUrl(url, origin)) {
|
} else if (canParseUrl(url, origin)) {
|
||||||
console.log(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);
|
||||||
|
|
||||||
return self.__scramjet$config.prefix + self.__scramjet$config.codec.encode(new URL(url, origin).href);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,8 @@ self.ScramjetServiceWorker = class ScramjetServiceWorker {
|
||||||
async fetch(event: FetchEvent) {
|
async fetch(event: FetchEvent) {
|
||||||
const url = new URL(self.__scramjet$bundle.rewriters.url.decodeUrl(event.request.url));
|
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
|
// implement header rewriting later
|
||||||
const response = await this.client.fetch(url, {
|
const response = await this.client.fetch(url, {
|
||||||
method: event.request.method,
|
method: event.request.method,
|
||||||
|
@ -26,6 +28,8 @@ self.ScramjetServiceWorker = class ScramjetServiceWorker {
|
||||||
headers: event.request.headers
|
headers: event.request.headers
|
||||||
});
|
});
|
||||||
|
|
||||||
|
self.__scramjet$bundle.rewriters.rewriteHeaders(response.headers);
|
||||||
|
|
||||||
let responseBody;
|
let responseBody;
|
||||||
|
|
||||||
if (event.request.destination === "document") {
|
if (event.request.destination === "document") {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue