Signatur
Beschreibung
Über Request.body liest du den Inhalt einer Anfrage als Datenstrom (ReadableStream<Uint8Array>). Du musst den Body also nicht vollständig in den Speicher laden wie bei text(), json() oder arrayBuffer(), sondern kannst ihn stückweise verarbeiten. Das lohnt sich bei großen Uploads, beim Prüfen oder Umschreiben von Anfragen in einem Service Worker und in serverseitigen Umgebungen wie Deno, Cloudflare Workers oder Node.js (ab 18 mit eingebautem fetch).
Wurde die Request ohne body-Option erzeugt, gibt die Eigenschaft null zurück. Das gilt immer für GET- und HEAD-Anfragen, weil diese keinen Body haben dürfen. Hast du beim Konstruktor einen String, ein Blob, FormData, URLSearchParams, einen ArrayBuffer oder einen ReadableStream übergeben, bekommst du ihn hier immer als Byte-Stream zurück.
Einen Body kannst du nur einmal auslesen. Sobald du aus dem Stream gelesen hast, gilt er als „gestört“ und request.bodyUsed ist true. Ab dann schlagen weitere Leseversuche fehl, auch mit text() oder json(). Brauchst du den Inhalt mehrfach, rufst du vorher request.clone() auf.
Rückgabewert
ReadableStream mit den Bytes des Bodys oder null, wenn die Anfrage keinen Body hat (z. B. bei GET/HEAD).Beispiele
Body einer POST-Anfrage stückweise lesen
const request = new Request('https://example.com/api/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'Ada' })
});
const reader = request.body.getReader();
const decoder = new TextDecoder();
let text = '';
while (true) {
const { done, value } = await reader.read();
if (done) break;
text += decoder.decode(value, { stream: true });
}
text += decoder.decode();
console.log(text);
console.log(request.bodyUsed);
GET-Anfragen haben keinen Body
const getRequest = new Request('https://example.com/daten');
console.log(getRequest.body);
// Vor dem Lesen immer auf null prüfen
const readSize = async (req) => {
if (!req.body) return 0;
const buffer = await new Response(req.body).arrayBuffer();
return buffer.byteLength;
};
console.log(await readSize(getRequest));
console.log(await readSize(new Request('https://example.com', { method: 'POST', body: 'Hallo' })));
Service Worker: Body protokollieren, ohne die Anfrage zu verbrauchen
self.addEventListener('fetch', (event) => {
const { request } = event;
if (request.method !== 'POST' || !request.body) return;
event.respondWith((async () => {
// Kopie lesen, Original unverändert weiterreichen
const copy = request.clone();
const bytes = (await new Response(copy.body).arrayBuffer()).byteLength;
console.log(`Upload an ${request.url}: ${bytes} Bytes`);
return fetch(request);
})());
});
Upload-Fortschritt über einen Stream-Body messen
const uploadWithProgress = async (file) => {
let sent = 0;
const progress = new TransformStream({
transform(chunk, controller) {
sent += chunk.byteLength;
console.log(`${Math.round((sent / file.size) * 100)} %`);
controller.enqueue(chunk);
}
});
const request = new Request('/upload', {
method: 'POST',
body: file.stream().pipeThrough(progress),
duplex: 'half' // Pflicht bei Stream-Bodys
});
console.log(request.body instanceof ReadableStream);
return fetch(request);
};
// Wichtig · Fallstricke
- Nur einmal lesbar: Nach dem ersten Lesen, auch durch
getReader(),pipeTo()oderjson(), istbodyUsedgleichtrue. Danach werfenclone()und alle Lesemethoden einenTypeError. Klone die Anfrage also, bevor du liest. - Gesperrter Stream: Solange ein Reader aktiv ist, ist der Stream gesperrt (
body.locked === true). Mitreader.releaseLock()gibst du ihn wieder frei. - GET/HEAD mit Body: Übergibst du einer
GET- oderHEAD-Anfrage einen Body, wirftnew Request()einenTypeError. - Stream als Body: Gibst du einen
ReadableStreamals Body an, verlangt die Spezifikationduplex: 'half'. Browser senden solche Streaming-Uploads in der Regel nur über HTTP/2 oder neuer. Außerdem ist dann kein CORS-freier Aufruf (no-cors) möglich. - Browser-Kompatibilität: Chromium-Browser haben
Request.bodylange alsundefinedzurückgegeben und unterstützen es erst ab Version 105. Firefox hat die Eigenschaft lange nicht angeboten. Prüfe vor dem Einsatz'body' in Request.prototypeoder nimm plattformübergreifendawait request.arrayBuffer()bzw.request.blob().