2023-07-25 16:04:30 +00:00
|
|
|
import type { OnBeforeRequestDetailsType, StreamFilter } from "./types.js";
|
2023-07-17 15:39:16 +00:00
|
|
|
import browser from "webextension-polyfill";
|
2022-09-08 11:28:31 +00:00
|
|
|
import { iterateStream, streamToArray } from "./util.js";
|
|
|
|
|
|
|
|
export default class RequestStream {
|
|
|
|
private _request: OnBeforeRequestDetailsType;
|
|
|
|
private _filter: StreamFilter;
|
|
|
|
private _contentFilter?: (data: Uint8Array) => Promise<Uint8Array>;
|
|
|
|
private _readableStream: ReadableStream;
|
|
|
|
|
|
|
|
constructor(
|
|
|
|
request: OnBeforeRequestDetailsType,
|
2023-07-17 15:39:16 +00:00
|
|
|
contentFilter?: (data: Uint8Array) => Promise<Uint8Array>,
|
2022-09-08 11:28:31 +00:00
|
|
|
) {
|
|
|
|
this._request = request;
|
|
|
|
this._contentFilter = contentFilter;
|
|
|
|
this._filter = browser.webRequest.filterResponseData(request.requestId);
|
|
|
|
this._stream = new TransformStream<Uint8Array>();
|
|
|
|
this._readableStream = this._stream.readable;
|
|
|
|
}
|
|
|
|
|
|
|
|
private _stream: TransformStream<Uint8Array>;
|
|
|
|
|
|
|
|
get stream(): TransformStream {
|
|
|
|
return this._stream;
|
|
|
|
}
|
|
|
|
|
|
|
|
get readableStream(): ReadableStream {
|
|
|
|
const [a, b] = this._readableStream.tee();
|
|
|
|
this._readableStream = a;
|
|
|
|
|
|
|
|
return b;
|
|
|
|
}
|
|
|
|
|
|
|
|
public start(): void {
|
|
|
|
this._filter.onstop = async () => {
|
|
|
|
if (this._contentFilter) {
|
|
|
|
const data = await this._contentFilter(
|
2023-07-17 15:39:16 +00:00
|
|
|
await streamToArray(this._readableStream),
|
2022-09-08 11:28:31 +00:00
|
|
|
);
|
|
|
|
this._filter.write(data);
|
|
|
|
this._filter.close();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
for await (const chunk of iterateStream(this._readableStream)) {
|
|
|
|
this._filter.write(chunk);
|
|
|
|
}
|
|
|
|
this._filter.close();
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
public async close() {
|
|
|
|
await this._stream.writable.close();
|
|
|
|
}
|
|
|
|
}
|