webRequest.StreamFilter.ondata
Ein Ereignis-Handler, der wiederholt aufgerufen wird, wenn Antwortdaten verfügbar sind. Dem Handler wird ein Event
object mit einer data
-Eigenschaft übergeben. Die data
-Eigenschaft enthält ein Datenstück der Antwort als ArrayBuffer
.
Um die Daten zu dekodieren, verwenden Sie entweder TextDecoder
oder Blob
.
Ohne einen ondata
-Listener erhalten Sie den ursprünglichen Antwortkörper nicht, und der Ausgabestrom ist leer, es sei denn, write
wird aufgerufen.
Beispiele
Dieses Beispiel fügt einen ondata
-Listener hinzu, der "Example" in der Antwort mit "WebExtension Example" ersetzt, indem die Methode replaceAll()
verwendet wird.
Hinweis: Dieses Beispiel funktioniert nur für Vorkommen von "Example", die vollständig in einem Datenstück enthalten sind, und nicht für solche, die über zwei Stücke hinweg verteilt sind (was bei großen Dokumenten ~0.1% der Zeit passieren könnte). Außerdem behandelt es nur UTF-8-kodierte Dokumente. Eine echte Implementierung müsste komplexer sein.
function listener(details) {
const filter = browser.webRequest.filterResponseData(details.requestId);
const decoder = new TextDecoder("utf-8");
const encoder = new TextEncoder();
filter.ondata = (event) => {
let str = decoder.decode(event.data, { stream: true });
// Just change any instance of Example in the HTTP response
// to WebExtension Example.
// Note that this will maybe not work as expected because the ending of the str can also
// be "<h1>Examp" (because it is not the full response). So, it is better
// to get the full response first and then doing the replace.
str = str.replaceAll("Example", "WebExtension Example");
filter.write(encoder.encode(str));
// Doing filter.disconnect(); here would make us process only
// the first chunk, and let the rest through unchanged. Note
// that this would break multi-byte characters that occur on
// the chunk boundary!
};
filter.onstop = (event) => {
filter.close();
};
}
browser.webRequest.onBeforeRequest.addListener(
listener,
{ urls: ["https://example.com/*"], types: ["main_frame"] },
["blocking"],
);
Ein weiteres Beispiel für die Verarbeitung großer Dokumente:
function listener(details) {
const filter = browser.webRequest.filterResponseData(details.requestId);
const decoder = new TextDecoder("utf-8");
const encoder = new TextEncoder();
const data = [];
filter.ondata = (event) => {
data.push(event.data);
};
filter.onstop = (event) => {
let str = "";
if (data.length === 1) {
str = decoder.decode(data[0]);
} else {
for (let i = 0; i < data.length; i++) {
const stream = i !== data.length - 1;
str += decoder.decode(data[i], { stream });
}
}
str = str.replaceAll("Example", "WebExtension $&");
filter.write(encoder.encode(str));
filter.close();
};
}
browser.webRequest.onBeforeRequest.addListener(
listener,
{ urls: ["https://example.com/"], types: ["main_frame"] },
["blocking"],
);
Hier ist eine andere Version:
function listener(details) {
const filter = browser.webRequest.filterResponseData(details.requestId);
const decoder = new TextDecoder("utf-8");
const encoder = new TextEncoder();
const data = [];
filter.ondata = (event) => {
data.push(event.data);
};
filter.onstop = (event) => {
let str = "";
for (const buffer of data) {
str += decoder.decode(buffer, { stream: true });
}
str += decoder.decode(); // end-of-stream
str = str.replaceAll("Example", "WebExtension $&");
filter.write(encoder.encode(str));
filter.close();
};
}
browser.webRequest.onBeforeRequest.addListener(
listener,
{ urls: ["https://example.com/"], types: ["main_frame"] },
["blocking"],
);
Das obige Beispiel kann auch so geschrieben werden:
function listener(details) {
const filter = browser.webRequest.filterResponseData(details.requestId);
const decoder = new TextDecoder("utf-8");
const encoder = new TextEncoder();
const data = [];
filter.ondata = (event) => {
data.push(decoder.decode(event.data, { stream: true }));
};
filter.onstop = (event) => {
data.push(decoder.decode());
let str = data.join("");
str = str.replaceAll("Example", "WebExtension $&");
filter.write(encoder.encode(str));
filter.close();
};
}
browser.webRequest.onBeforeRequest.addListener(
listener,
{ urls: ["https://example.com/"], types: ["main_frame"] },
["blocking"],
);
Dieses Beispiel verwendet einen Blob
:
function listener(details) {
const filter = browser.webRequest.filterResponseData(details.requestId);
const encoder = new TextEncoder();
const data = [];
filter.ondata = (event) => {
data.push(event.data);
};
filter.onstop = async (event) => {
const blob = new Blob(data, { type: "text/html" });
let str = await blob.text();
str = str.replaceAll("Example", "WebExtension $&");
filter.write(encoder.encode(str));
filter.close();
};
}
browser.webRequest.onBeforeRequest.addListener(
listener,
{ urls: ["https://example.com/"], types: ["main_frame"] },
["blocking"],
);
Dieses Beispiel nutzt die DOMParser
-Schnittstelle:
function listener(details) {
const filter = browser.webRequest.filterResponseData(details.requestId);
const encoder = new TextEncoder();
const parser = new DOMParser();
const data = [];
filter.ondata = (event) => {
data.push(event.data);
};
filter.onstop = async (event) => {
const blob = new Blob(data, { type: "text/html" });
const str = await blob.text();
const doc = parser.parseFromString(str, blob.type);
const nodes = doc.querySelectorAll("title, h1");
for (const node of nodes) {
node.innerText = node.innerText.replaceAll("Example", "WebExtension $&");
}
filter.write(encoder.encode(doc.documentElement.outerHTML));
filter.close();
};
}
browser.webRequest.onBeforeRequest.addListener(
listener,
{ urls: ["https://example.com/"], types: ["main_frame"] },
["blocking"],
);
Dieses Beispiel kombiniert alle Puffer zu einem einzigen Puffer:
function listener(details) {
const filter = browser.webRequest.filterResponseData(details.requestId);
const decoder = new TextDecoder("utf-8");
const encoder = new TextEncoder();
const data = [];
filter.ondata = (event) => {
data.push(new Uint8Array(event.data));
};
filter.onstop = (event) => {
let combinedLength = 0;
for (const buffer of data) {
combinedLength += buffer.length;
}
const combinedArray = new Uint8Array(combinedLength);
let writeOffset = 0;
for (const buffer of data) {
combinedArray.set(buffer, writeOffset);
writeOffset += buffer.length;
}
let str = decoder.decode(combinedArray);
str = str.replaceAll("Example", "WebExtension $&");
filter.write(encoder.encode(str));
filter.close();
};
}
browser.webRequest.onBeforeRequest.addListener(
listener,
{ urls: ["https://example.com/"], types: ["main_frame"] },
["blocking"],
);
Das obige Beispiel kann auch so geschrieben werden:
function listener(details) {
const filter = browser.webRequest.filterResponseData(details.requestId);
const decoder = new TextDecoder("utf-8");
const encoder = new TextEncoder();
const data = [];
filter.ondata = (event) => {
data.push(event.data);
};
filter.onstop = async (event) => {
const blob = new Blob(data, { type: "text/html" });
const buffer = await blob.arrayBuffer();
let str = decoder.decode(buffer);
str = str.replaceAll("Example", "WebExtension $&");
filter.write(encoder.encode(str));
filter.close();
};
}
browser.webRequest.onBeforeRequest.addListener(
listener,
{ urls: ["https://example.com/"], types: ["main_frame"] },
["blocking"],
);
Dieses Beispiel zeigt, wie man erkennen kann, ob es sich um das letzte Stück in der Antwort handelt:
function listener(details) {
const filter = browser.webRequest.filterResponseData(details.requestId);
const encoder = new TextEncoder();
const decoder = new TextDecoder("utf-8");
let str = "";
filter.ondata = (event) => {
let stream = true;
const data = new Uint8Array(event.data.slice(-8, -1));
if (String.fromCharCode(...data) === "</html>") {
stream = false; // end-of-stream
}
str += decoder.decode(event.data, { stream });
};
filter.onstop = (event) => {
str = str.replaceAll("Example", "WebExtension $&");
filter.write(encoder.encode(str));
filter.close();
};
}
browser.webRequest.onBeforeRequest.addListener(
listener,
{ urls: ["https://example.com/"], types: ["main_frame"] },
["blocking"],
);
Browser-Kompatibilität
BCD tables only load in the browser