22 BareClient ,
33 BareHeaders ,
44 BareResponseFetch ,
5+ TransferrableResponse ,
56} from "@mercuryworkshop/bare-mux-custom" ;
67
78import { CookieJar } from "@/shared/cookie" ;
@@ -14,7 +15,7 @@ import {
1415} from "@rewriters/url" ;
1516import { rewriteJs } from "@rewriters/js" ;
1617import { ScramjetHeaders } from "@/shared/headers" ;
17- import { config , flagEnabled , iface } from "@/shared" ;
18+ import { Clientbound , config , flagEnabled , iface , Serverbound } from "@/shared" ;
1819import { rewriteHtml } from "@rewriters/html" ;
1920import { rewriteCss } from "@rewriters/css" ;
2021import { rewriteWorkers } from "@rewriters/worker" ;
@@ -57,6 +58,17 @@ export type FetchHandler = {
5758 cookieJar : CookieJar ;
5859 crossOriginIsolated ?: boolean ;
5960 prefix : URL ;
61+
62+ sendClientbound < K extends keyof Clientbound > (
63+ type : K ,
64+ msg : Clientbound [ K ] [ 0 ]
65+ ) : Promise < Clientbound [ K ] [ 1 ] > ;
66+ onServerbound < K extends keyof Serverbound > (
67+ type : K ,
68+ listener : ( msg : Serverbound [ K ] [ 0 ] ) => Promise < Serverbound [ K ] [ 1 ] >
69+ ) : void ;
70+ fetchDataUrl ( dataUrl : string ) : Promise < BareResponseFetch > ;
71+ fetchBlobUrl ( blobUrl : string ) : Promise < BareResponseFetch > ;
6072} ;
6173
6274export class ScramjetFetchHandler extends EventTarget {
@@ -65,14 +77,25 @@ export class ScramjetFetchHandler extends EventTarget {
6577 public crossOriginIsolated : boolean = false ;
6678 public prefix : URL ;
6779
80+ public sendClientbound : < K extends keyof Clientbound > (
81+ type : K ,
82+ msg : Clientbound [ K ] [ 0 ]
83+ ) => Promise < Clientbound [ K ] [ 1 ] > ;
84+
85+ public fetchDataUrl : ( dataUrl : string ) => Promise < BareResponseFetch > ;
86+ public fetchBlobUrl : ( blobUrl : string ) => Promise < BareResponseFetch > ;
87+
6888 constructor ( init : FetchHandler ) {
6989 super ( ) ;
7090 this . client = init . client ;
7191 this . cookieJar = init . cookieJar ;
7292 this . crossOriginIsolated = init . crossOriginIsolated || false ;
7393 this . prefix = init . prefix ;
94+ this . sendClientbound = init . sendClientbound ;
95+ this . fetchDataUrl = init . fetchDataUrl ;
96+ this . fetchBlobUrl = init . fetchBlobUrl ;
7497
75- iface . onServerbound ( "setCookie" , ( { cookie, url } ) => {
98+ init . onServerbound ( "setCookie" , ( { cookie, url } ) => {
7699 console . log ( "recv'd cookies" ) ;
77100 this . cookieJar . setCookies ( [ cookie ] , new URL ( url ) ) ;
78101
@@ -387,12 +410,18 @@ async function handleBlobOrDataUrlFetch(
387410 parsed : ScramjetFetchParsed
388411) : Promise < ScramjetFetchResponse > {
389412 let dataUrl = context . rawUrl . pathname . substring ( config . prefix . length ) ;
413+ let response : BareResponseFetch ;
414+
390415 if ( dataUrl . startsWith ( "blob:" ) ) {
391416 dataUrl = unrewriteBlob ( dataUrl , parsed . meta ) ;
417+ response = await handler . fetchBlobUrl ( dataUrl ) ;
418+ } else {
419+ response = await handler . fetchDataUrl ( dataUrl ) ;
392420 }
393- const response : Partial < BareResponseFetch > = await fetch ( dataUrl , { } ) ;
421+
394422 const url = dataUrl . startsWith ( "blob:" ) ? dataUrl : "(data url)" ;
395423 response . finalURL = url ;
424+
396425 let body : BodyType ;
397426 if ( response . body ) {
398427 body = await rewriteBody (
@@ -415,66 +444,6 @@ async function handleBlobOrDataUrlFetch(
415444 headers : headers ,
416445 } ;
417446}
418- // async function handleDownload(
419- // context: ScramjetFetchContext,
420- // parsed: ScramjetFetchParsed
421- // ) {
422- // if (flagEnabled("interceptDownloads", parsed.url)) {
423- // if (!client) {
424- // throw new Error("cant find client");
425- // }
426- // let filename: string | null = null;
427- // const disp = responseHeaders["content-disposition"];
428- // if (typeof disp === "string") {
429- // const filenameMatch = disp.match(/filename=["']?([^"';\n]*)["']?/i);
430- // if (filenameMatch && filenameMatch[1]) {
431- // filename = filenameMatch[1];
432- // }
433- // }
434- // const length = responseHeaders["content-length"];
435- // // there's no reliable way of finding the top level client that made the request
436- // // just take the first one and hope
437- // let clis = await clients.matchAll({
438- // type: "window",
439- // });
440- // // only want controller windows
441- // clis = clis.filter((e) => !e.url.includes(config.prefix));
442- // if (clis.length < 1) {
443- // throw Error("couldn't find a controller client to dispatch download to");
444- // }
445- // const download: ScramjetDownload = {
446- // filename,
447- // url: url.href,
448- // type: responseHeaders["content-type"],
449- // body: response.body,
450- // length: Number(length),
451- // };
452- // clis[0].postMessage(
453- // {
454- // scramjet$type: "download",
455- // download,
456- // } as MessageW2C,
457- // [response.body]
458- // );
459- // // endless vortex reference
460- // await new Promise(() => {});
461- // } else {
462- // // manually rewrite for regular browser download
463- // const header = responseHeaders["content-disposition"];
464- // // validate header and test for filename
465- // if (!/\s*?((inline|attachment);\s*?)filename=/i.test(header)) {
466- // // if filename= wasn"t specified then maybe the remote specified to download this as an attachment?
467- // // if it"s invalid then we can still possibly test for the attachment/inline type
468- // const type = /^\s*?attachment/i.test(header) ? "attachment" : "inline";
469- // // set the filename
470- // const [filename] = new URL(response.finalURL).pathname
471- // .split("/")
472- // .slice(-1);
473- // responseHeaders["content-disposition"] =
474- // `${type}; filename=${JSON.stringify(filename)}`;
475- // }
476- // }
477- // }
478447
479448async function handleCookies (
480449 context : ScramjetFetchContext ,
0 commit comments