Signatur
Beschreibung
Die Methode bytes() gehört zum Body-Mixin, das Request und Response gemeinsam nutzen. Sie liest den Datenstrom des Anfragekörpers bis zum Ende und liefert die Rohdaten als Uint8Array. Im Vergleich zu arrayBuffer() sparst du dir damit den Zwischenschritt new Uint8Array(await request.arrayBuffer()).
Nützlich ist das vor allem dort, wo du eine Anfrage empfängst oder abfängst, statt sie selbst zu senden: in einem Service Worker im fetch-Event, in serverseitigen Laufzeitumgebungen wie Node.js, Deno, Bun oder Cloudflare Workers, oder in Tests, in denen du ein selbst gebautes Request-Objekt prüfen willst. Typische Anwendungen sind Prüfsummen und Signaturen (z. B. HMAC-Prüfung bei Webhooks), das Weiterleiten von Binär-Uploads und das Auswerten eigener Binärformate.
Der Körper lässt sich nur einmal lesen. Danach steht request.bodyUsed auf true und jeder weitere Leseversuch (bytes(), text(), json() …) schlägt fehl. Wenn du den Körper mehrfach brauchst, zum Beispiel um die Anfrage nach dem Prüfen noch weiterzuleiten, lies ihn vorher über request.clone() aus.
Rückgabewert
Uint8Array mit dem vollständigen Anfragekörper erfüllt wird. Hat die Anfrage keinen Körper (body === null), ist das Array leer (Länge 0).Beispiele
Körper einer selbst erstellten Anfrage als Bytes lesen
const request = new Request('https://example.com/api/upload', {
method: 'POST',
body: 'Hallo'
});
const bytes = await request.bytes();
console.log(bytes);
console.log(request.bodyUsed);
Webhook-Signatur (SHA-256) über den Rohkörper berechnen
// z. B. in einem Cloudflare Worker, Deno oder Bun
const sha256Hex = async (data) => {
const hash = await crypto.subtle.digest('SHA-256', data);
return [...new Uint8Array(hash)]
.map((b) => b.toString(16).padStart(2, '0'))
.join('');
};
const handleWebhook = async (request) => {
// Klon lesen, damit das Original weitergereicht werden kann
const raw = await request.clone().bytes();
const digest = await sha256Hex(raw);
const expected = request.headers.get('x-body-sha256');
if (digest !== expected) {
return new Response('Ungültige Signatur', { status: 401 });
}
const payload = await request.json();
return Response.json({ ok: true, event: payload.event });
};
// Test
const body = JSON.stringify({ event: 'order.created' });
const hash = await sha256Hex(new TextEncoder().encode(body));
const res = await handleWebhook(new Request('https://example.com/hook', {
method: 'POST',
headers: { 'x-body-sha256': hash },
body
}));
console.log(res.status, await res.json());
Binär-Upload im Service Worker mit Rückfall auf arrayBuffer()
const readBytes = async (req) =>
typeof req.bytes === 'function'
? req.bytes()
: new Uint8Array(await req.arrayBuffer());
self.addEventListener('fetch', (event) => {
const { request } = event;
if (request.method !== 'PUT' || !request.url.endsWith('/upload')) return;
event.respondWith((async () => {
const data = await readBytes(request.clone());
// Magic Number prüfen: PNG beginnt mit 0x89 0x50 0x4E 0x47
const isPng = data[0] === 0x89 && data[1] === 0x50 &&
data[2] === 0x4e && data[3] === 0x47;
if (!isPng) {
return new Response('Nur PNG erlaubt', { status: 415 });
}
return fetch(request);
})());
});
// Wichtig · Fallstricke
- Nur einmal lesbar: Wurde der Körper schon gelesen (
bodyUsed === true) oder ist der Datenstrom gesperrt, wird das Promise mit einemTypeErrorabgelehnt. Vorherrequest.clone()verwenden, und zwar bevor du anfängst zu lesen. - Speicherbedarf: Der gesamte Körper landet im Arbeitsspeicher. Große Uploads verarbeitest du besser als Datenstrom über
request.body(ReadableStream). Lässt sich der Puffer nicht anlegen, wird das Promise mit einemRangeErrorabgelehnt. - Abbruch: Wurde die Anfrage mit einem
AbortSignalerstellt und dieses Signal abgebrochen, wird das Promise mit einerAbortError-DOMExceptionabgelehnt. - Kompatibilität: Die Methode ist relativ neu (Firefox 128, Safari 18, Chrome 132). Für ältere Umgebungen per Feature-Erkennung auf
new Uint8Array(await request.arrayBuffer())zurückfallen. - Für Text ist
text()besser geeignet, weil es automatisch als UTF-8 dekodiert.bytes()liefert die unveränderten Rohbytes, und genau die brauchst du für Signaturen.