Start · Sprachen · JavaScript · Referenz · Request.body

Request.body

Eigenschaft

Schreibgeschützte Eigenschaft, die den Body einer <code>Request</code> als <code>ReadableStream</code> liefert – oder <code>null</code>, wenn die Anfrage keinen Body hat.

seit JavaScript Chrome/Edge 105+, Safari 11.1+; Firefox: Unterstüt Kategorie: webapi

Signatur

get Request.prototype.body

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

Typ
ReadableStream<Uint8Array> | null
Beschreibung
Ein 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);
{"name":"Ada"} true

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' })));
null 0 5

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 an https://example.com/upload: 1024 Bytes

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);
};
true 25 % 50 % 75 % 100 %

// Wichtig · Fallstricke

  • Nur einmal lesbar: Nach dem ersten Lesen, auch durch getReader(), pipeTo() oder json(), ist bodyUsed gleich true. Danach werfen clone() und alle Lesemethoden einen TypeError. Klone die Anfrage also, bevor du liest.
  • Gesperrter Stream: Solange ein Reader aktiv ist, ist der Stream gesperrt (body.locked === true). Mit reader.releaseLock() gibst du ihn wieder frei.
  • GET/HEAD mit Body: Übergibst du einer GET- oder HEAD-Anfrage einen Body, wirft new Request() einen TypeError.
  • Stream als Body: Gibst du einen ReadableStream als Body an, verlangt die Spezifikation duplex: '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.body lange als undefined zurückgegeben und unterstützen es erst ab Version 105. Firefox hat die Eigenschaft lange nicht angeboten. Prüfe vor dem Einsatz 'body' in Request.prototype oder nimm plattformübergreifend await request.arrayBuffer() bzw. request.blob().