Skip to content

res.send: send DataView bytes instead of silently dropping them - #7522

Closed
piyush295 wants to merge 1 commit into
expressjs:masterfrom
piyush295:fix/res-send-dataview
Closed

piyush295 wants to merge 1 commit into
expressjs:masterfrom
piyush295:fix/res-send-dataview

Conversation

@piyush295

Copy link
Copy Markdown

Bug (fixes #7510)

res.send detects DataView via ArrayBuffer.isView() and sets the binary Content-Type, but the chunk then falls through to Buffer.from(chunk, encoding). Buffer.from(dataView) returns an empty Buffer, so a DataView-bodied response went out as 200 with Content-Length: 0 and no payload.

Repro:

app.get('/', (req, res) => {
  const bytes = new Uint8Array([0, 1, 2, 3, 0])
  res.send(new DataView(bytes.buffer, 1, 3))
})
// GET / returned empty instead of the three bytes 01 02 03

Fix

Convert a DataView to a Buffer over its exact byte range right after the Content-Type decision, using Buffer.from(buffer, byteOffset, byteLength). Typed arrays (Uint8Array, Uint16Array, …) continue through the existing fast path untouched, so the Uint16Array compat raised on #7433 is preserved.

if (chunk instanceof DataView) {
  chunk = Buffer.from(chunk.buffer, chunk.byteOffset, chunk.byteLength);
  encoding = undefined;
}

Tests

Two regression tests added to test/res.send.js:

  1. DataView over the whole buffer — asserts Content-Length: 3 and body "hey".
  2. DataView with offset and length — [0xff, 0x68, 0x65, 0x79, 0xff] with new DataView(buf, 1, 3) — asserts the surrounding 0xff bytes don't leak into the response.

All 1263 existing tests still pass. npm run lint is clean.

res.send detects DataView via ArrayBuffer.isView() and sets the binary
Content-Type, but the chunk then falls through to Buffer.from(chunk,
encoding). Buffer.from(dataView) returns an empty Buffer, so a
DataView-bodied response went out as 200 with Content-Length: 0 and no
payload.

Convert a DataView to a Buffer over its exact byte range right after
the Content-Type decision, using Buffer.from(buffer, byteOffset,
byteLength). Typed arrays (Uint8Array, Uint16Array, …) continue through
the existing fast path untouched, so compat with Uint16Array raised on
#7433 is preserved.

Two regression tests:
- DataView over the whole backing buffer sends the full bytes and the
  correct Content-Length.
- DataView with explicit byteOffset and byteLength sends only its slice
  (verifying that we don't send the surrounding bytes).

All 1263 existing tests still pass.

Fixes #7510.
@krzysdz

krzysdz commented Oct 16, 2026

Copy link
Copy Markdown
Contributor

Duplicate of #7511

@krzysdz krzysdz marked this as a duplicate of #7511 Oct 16, 2026
@krzysdz krzysdz closed this Oct 16, 2026
@piyush295

Copy link
Copy Markdown
Author

Thanks for the heads-up @krzysdz — missed #7511 when I was triaging #7510, apologies for the duplicate. Deferring to that PR.

@piyush295
piyush295 deleted the fix/res-send-dataview branch October 16, 2026 13:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

res.send(DataView) silently drops the view’s bytes

2 participants