mirror of
https://github.com/MercuryWorkshop/scramjet.git
synced 2025-05-14 06:50:01 -04:00
Fix header rewriting
Fix header rewriting, revamp html rewriting, add types to bare-mux from bare-client, prefetch scramjet scripts for faster load
This commit is contained in:
parent
8a68a17e7a
commit
23fd5a7b83
7 changed files with 75 additions and 125 deletions
|
@ -14,24 +14,24 @@ const devServer = createServer({
|
|||
outdir: "./dist",
|
||||
bundle: true,
|
||||
sourcemap: true,
|
||||
logLevel: 'info',
|
||||
logLevel: "info",
|
||||
plugins: [
|
||||
copy({
|
||||
resolveFrom: "cwd",
|
||||
assets: [
|
||||
{
|
||||
from: ['./node_modules/@mercuryworkshop/bare-mux/dist/bare.cjs'],
|
||||
to: ['./static/bare-mux.js'],
|
||||
from: ["./node_modules/@mercuryworkshop/bare-mux/dist/bare.cjs"],
|
||||
to: ["./static/bare-mux.js"],
|
||||
},
|
||||
{
|
||||
from: ['./node_modules/@mercuryworkshop/bare-as-module3/dist/bare.cjs'],
|
||||
to: ['./static/bare-client.js'],
|
||||
from: ["./node_modules/@mercuryworkshop/bare-as-module3/dist/bare.cjs"],
|
||||
to: ["./static/bare-client.js"],
|
||||
},
|
||||
{
|
||||
from: ["./dist/*"],
|
||||
to: ["./static"]
|
||||
},
|
||||
],
|
||||
],
|
||||
}),
|
||||
time()
|
||||
]
|
||||
|
|
|
@ -25,8 +25,9 @@
|
|||
"type": "module",
|
||||
"dependencies": {
|
||||
"@fastify/static": "^7.0.3",
|
||||
"@mercuryworkshop/bare-mux": "^1.1.0",
|
||||
"@mercuryworkshop/bare-as-module3": "^2.2.0-alpha",
|
||||
"@mercuryworkshop/bare-mux": "^1.1.0",
|
||||
"@tomphttp/bare-client": "2.2.0-alpha",
|
||||
"@tomphttp/bare-server-node": "^2.0.3",
|
||||
"concurrently": "^8.2.2",
|
||||
"dom-serializer": "^2.0.0",
|
||||
|
|
26
pnpm-lock.yaml
generated
26
pnpm-lock.yaml
generated
|
@ -8,6 +8,12 @@ dependencies:
|
|||
'@fastify/static':
|
||||
specifier: ^7.0.3
|
||||
version: 7.0.3
|
||||
'@mercuryworkshop/bare-as-module3':
|
||||
specifier: ^2.2.0-alpha
|
||||
version: 2.2.0-alpha
|
||||
'@mercuryworkshop/bare-mux':
|
||||
specifier: ^1.1.0
|
||||
version: 1.1.0
|
||||
'@tomphttp/bare-client':
|
||||
specifier: 2.2.0-alpha
|
||||
version: 2.2.0-alpha
|
||||
|
@ -385,6 +391,17 @@ packages:
|
|||
engines: {node: '>=8'}
|
||||
dev: false
|
||||
|
||||
/@mercuryworkshop/bare-as-module3@2.2.0-alpha:
|
||||
resolution: {integrity: sha512-Vbk07NDfwENaiadfZFdG+FkjZb6dQODhykYhMpY7k2TZJanuDjs+MDIucpiqufymCTemx+9uAnv91v/GTxqJsg==}
|
||||
dev: false
|
||||
|
||||
/@mercuryworkshop/bare-mux@1.1.0:
|
||||
resolution: {integrity: sha512-E+d2GZEdbnUrGTx8AOrDVe0d7Cxz57rjDWBn9xAHH65G68PQkVY17j0EXAurFXF/sJzbjLTPcJZvHZQA2P/IVQ==}
|
||||
dependencies:
|
||||
'@types/uuid': 9.0.8
|
||||
uuid: 9.0.1
|
||||
dev: false
|
||||
|
||||
/@nodelib/fs.scandir@2.1.5:
|
||||
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
|
||||
engines: {node: '>= 8'}
|
||||
|
@ -457,6 +474,10 @@ packages:
|
|||
resolution: {integrity: sha512-jBhFui72jyO0Tpsq/8AvL7GRJKiuUxdHPD9rrSRhf2SSElCn61yTyU2G133IlBVvBumCH4T5FDjmjbAG7MU9tg==}
|
||||
dev: true
|
||||
|
||||
/@types/uuid@9.0.8:
|
||||
resolution: {integrity: sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==}
|
||||
dev: false
|
||||
|
||||
/@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.57.0)(typescript@5.4.5):
|
||||
resolution: {integrity: sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==}
|
||||
engines: {node: ^16.0.0 || >=18.0.0}
|
||||
|
@ -2026,6 +2047,11 @@ packages:
|
|||
dependencies:
|
||||
punycode: 2.3.1
|
||||
|
||||
/uuid@9.0.1:
|
||||
resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==}
|
||||
hasBin: true
|
||||
dev: false
|
||||
|
||||
/which@2.0.2:
|
||||
resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
|
||||
engines: {node: '>= 8'}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { encodeUrl } from "./url";
|
||||
import { BareHeaders } from "@tomphttp/bare-client";
|
||||
|
||||
const cspHeaders = [
|
||||
"cross-origin-embedder-policy",
|
||||
|
@ -25,26 +26,19 @@ const urlHeaders = [
|
|||
"referer"
|
||||
];
|
||||
|
||||
export function rewriteHeaders(headers: Headers, origin?: string) {
|
||||
export function rewriteHeaders(headers: BareHeaders, origin?: string) {
|
||||
cspHeaders.forEach((header) => {
|
||||
if (headers.has(header)) {
|
||||
headers.delete(header);
|
||||
}
|
||||
delete headers[header];
|
||||
delete headers[header.toLowerCase()];
|
||||
});
|
||||
|
||||
urlHeaders.forEach((header) => {
|
||||
if (headers.has(header)) {
|
||||
headers.set(header, encodeUrl(headers.get(header), origin));
|
||||
if (headers[header]) {
|
||||
headers[header] = encodeUrl(headers[header] as string, origin);
|
||||
} else if (headers[header.toLowerCase()]) {
|
||||
headers[header.toLowerCase()] = encodeUrl(headers[header.toLowerCase()] as string, origin);
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
if (headers.has("link")) {
|
||||
let link = headers.get("link");
|
||||
|
||||
link = link.replace(/<(.*?)>/g, (match, g1) => {
|
||||
return `<${encodeUrl(g1, origin)}>`;
|
||||
});
|
||||
|
||||
headers.set("link", link);
|
||||
}
|
||||
return headers;
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
import { Parser } from "htmlparser2";
|
||||
import { DomHandler, hasChildren } from "domhandler";
|
||||
import { hasAttrib, getAttributeValue } from "domutils";
|
||||
import { hasAttrib } from "domutils";
|
||||
import render from "dom-serializer";
|
||||
import { encodeUrl } from "./url";
|
||||
import { rewriteCss } from "./css";
|
||||
|
@ -20,97 +20,27 @@ export function rewriteHtml(html: string, 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
|
||||
if (hasAttrib(node, "nonce")) {
|
||||
delete node.attribs.nonce;
|
||||
}
|
||||
/* csp attributes */
|
||||
if (hasAttrib(node, "nonce")) delete node.attribs.nonce;
|
||||
if (hasAttrib(node, "integrity")) delete node.attribs.integrity;
|
||||
if (hasAttrib(node, "csp")) delete node.attribs.csp;
|
||||
|
||||
if (node.name === "a" && hasAttrib(node, "href")) {
|
||||
node.attribs.href = encodeUrl(node.attribs.href, origin);
|
||||
} else if (node.name === "iframe") {
|
||||
if (hasAttrib(node, "src")) {
|
||||
node.attribs.src = encodeUrl(node.attribs.src, origin);
|
||||
}
|
||||
/* url attributes */
|
||||
if (hasAttrib(node, "src")) node.attribs.src = encodeUrl(node.attribs.src, origin);
|
||||
if (hasAttrib(node, "href")) node.attribs.href = encodeUrl(node.attribs.href, origin);
|
||||
if (hasAttrib(node, "data")) node.attribs.data = encodeUrl(node.attribs.data, origin);
|
||||
if (hasAttrib(node, "formaction")) node.attribs.formaction = encodeUrl(node.attribs.formaction, origin);
|
||||
if (hasAttrib(node, "form")) node.attribs.action = encodeUrl(node.attribs.action, origin);
|
||||
|
||||
if (hasAttrib(node, "srcdoc")) {
|
||||
node.attribs.srcdoc = rewriteHtml(node.attribs.srcdoc, origin);
|
||||
}
|
||||
/* other */
|
||||
if (hasAttrib(node, "srcdoc")) node.attribs.srcdoc = rewriteHtml(node.attribs.srcdoc, origin);
|
||||
if (hasAttrib(node, "srcset")) node.attribs.srcset = rewriteSrcset(node.attribs.srcset, origin);
|
||||
if (hasAttrib(node, "imagesrcset")) node.attribs.imagesrcset = rewriteSrcset(node.attribs.imagesrcset, origin);
|
||||
|
||||
if (hasAttrib(node, "csp")) {
|
||||
delete node.attribs.csp;
|
||||
}
|
||||
} else if (node.name === "link") {
|
||||
if (hasAttrib(node, "integrity")) {
|
||||
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") {
|
||||
if (hasAttrib(node, "integrity")) {
|
||||
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);
|
||||
console.log(node.attribs.src);
|
||||
}
|
||||
}
|
||||
|
||||
// implement js rewriting when done
|
||||
} else if (node.name === "img" && hasAttrib(node, "src")) {
|
||||
if (hasAttrib(node, "src")) {
|
||||
node.attribs.src = encodeUrl(node.attribs.src, origin);
|
||||
}
|
||||
|
||||
if (hasAttrib(node, "srcset")) {
|
||||
node.attribs.srcset = rewriteSrcset(node.attribs.srcset);
|
||||
}
|
||||
} else if (node.name === "object") {
|
||||
node.attribs.data = encodeUrl(node.attribs.data, origin);
|
||||
} else if (node.name === "embed") {
|
||||
node.attribs.src = encodeUrl(node.attribs.src, origin);
|
||||
} else if (node.name === "source") {
|
||||
if (hasAttrib(node, "src")) {
|
||||
node.attribs.src = encodeUrl(node.attribs.src, origin);
|
||||
}
|
||||
|
||||
if (hasAttrib(node, "srcset")) {
|
||||
node.attribs.srcset = rewriteSrcset(node.attribs.srcset);
|
||||
}
|
||||
} else if (node.name === "form") {
|
||||
node.attribs.action = encodeUrl(node.attribs.action, origin);
|
||||
} else if (node.name === "area") {
|
||||
node.attribs.href = encodeUrl(node.attribs.href, origin);
|
||||
} else if (node.name === "base" && hasAttrib(node, "href")) {
|
||||
node.attribs.href = encodeUrl(node.attribs.href, origin);
|
||||
} else if (node.name === "input") {
|
||||
if (hasAttrib(node, "formaction")) {
|
||||
node.attribs.formaction = encodeUrl(node.attribs.formaction, origin);
|
||||
}
|
||||
} else if (node.name === "audio") {
|
||||
node.attribs.src = encodeUrl(node.attribs.src, origin);
|
||||
} else if (node.name === "button") {
|
||||
if (hasAttrib(node, "formaction")) {
|
||||
node.attribs.formaction = encodeUrl(node.attribs.formaction, origin);
|
||||
}
|
||||
} else if (node.name === "track") {
|
||||
node.attribs.src = encodeUrl(node.attribs.src, origin);
|
||||
} else if (node.name === "video") {
|
||||
node.attribs.src = encodeUrl(node.attribs.src, origin);
|
||||
} else if (node.name === "meta") {
|
||||
if (hasAttrib(node, "http-equiv") && node.attribs["http-equiv"] === "content-security-policy") {
|
||||
delete node.attribs["http-equiv"];
|
||||
}
|
||||
}
|
||||
if (node.name === "style" && hasChildren(node)) node.children[0].data = rewriteCss(node.children[0].data, origin);
|
||||
// if (node.name === "script" && /((application|text)\/javascript)|importmap|undefined/.test(node.attribs.type) && !!node.children[0].data) {
|
||||
// node.children[0].data = rewriteJs(node.children[0].data);
|
||||
// }
|
||||
|
||||
if (node.childNodes) {
|
||||
for (const childNode in node.childNodes) {
|
||||
|
|
|
@ -2,6 +2,7 @@ importScripts("/scramjet.codecs.js");
|
|||
importScripts("/scramjet.config.js");
|
||||
importScripts("/scramjet.bundle.js");
|
||||
import { BareClient } from "@mercuryworkshop/bare-mux";
|
||||
import { BareResponseFetch } from "@tomphttp/bare-client"
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
|
@ -19,19 +20,16 @@ self.ScramjetServiceWorker = class ScramjetServiceWorker {
|
|||
async fetch(event: FetchEvent) {
|
||||
const url = new URL(self.__scramjet$bundle.rewriters.url.decodeUrl(event.request.url));
|
||||
|
||||
let headers = new Headers(event.request.headers);
|
||||
self.__scramjet$bundle.rewriters.rewriteHeaders(headers);
|
||||
|
||||
// implement header rewriting later
|
||||
const response = await this.client.fetch(url, {
|
||||
const response: BareResponseFetch = await this.client.fetch(url, {
|
||||
method: event.request.method,
|
||||
body: event.request.body,
|
||||
headers
|
||||
headers: event.request.headers
|
||||
});
|
||||
|
||||
self.__scramjet$bundle.rewriters.rewriteHeaders(response.headers);
|
||||
|
||||
let responseBody;
|
||||
const responseHeaders = self.__scramjet$bundle.rewriters.rewriteHeaders(response.rawHeaders, origin);
|
||||
|
||||
if (event.request.destination === "document") {
|
||||
responseBody = self.__scramjet$bundle.rewriters.rewriteHtml(await response.text(), url.origin);
|
||||
|
@ -43,11 +41,12 @@ self.ScramjetServiceWorker = class ScramjetServiceWorker {
|
|||
responseBody = response.body;
|
||||
}
|
||||
|
||||
if (crossOriginIsolated) {
|
||||
response.headers['Cross-Origin-Embedder-Policy'] = 'require-corp';
|
||||
}
|
||||
// if (crossOriginIsolated) {
|
||||
// response.headers["Cross-Origin-Embedder-Policy"] = "require-cors";
|
||||
// }
|
||||
|
||||
return new Response(responseBody, {
|
||||
headers: response.headers,
|
||||
headers: responseHeaders as HeadersInit,
|
||||
status: response.status,
|
||||
statusText: response.statusText
|
||||
})
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Document</title>
|
||||
<link rel="preload" as="script" href="./scramjet.worker.js">
|
||||
<link rel="preload" as="script" href="./scramjet.bundle.js">
|
||||
<link rel="prefetch" href="./scramjet.worker.js">
|
||||
<link rel="prefetch" href="./scramjet.bundle.js">
|
||||
<script src="./bare-mux.js" defer></script>
|
||||
<script src="./bare-client.js" defer></script>
|
||||
</head>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue