From 542756f66732dfd4579c71951830a0b39ba05d57 Mon Sep 17 00:00:00 2001 From: Oubaida Date: Fri, 7 Aug 2026 23:43:20 +0300 Subject: [PATCH] fix: support raw ArrayBuffer in res.send (#7362) --- lib/response.js | 10 +++++++++- test/res.send.js | 26 +++++++++++++++++--------- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/lib/response.js b/lib/response.js index b4755a5c060..da63b8c0fad 100644 --- a/lib/response.js +++ b/lib/response.js @@ -146,12 +146,16 @@ res.send = function send(body) { case 'boolean': case 'number': case 'object': + if (chunk === null) { chunk = ''; - } else if (ArrayBuffer.isView(chunk)) { + } else if (ArrayBuffer.isView(chunk) || chunk instanceof ArrayBuffer) { if (!this.get('Content-Type')) { this.type('bin'); } + if (chunk instanceof ArrayBuffer) { + chunk = Buffer.from(chunk); + } } else { return this.json(chunk); } @@ -166,9 +170,13 @@ res.send = function send(body) { // Content-Length should be added only if there is no Transfer-Encoding header var len; if (chunk !== undefined && !this.get('Transfer-Encoding')) { + if (Buffer.isBuffer(chunk)) { // get length of Buffer len = chunk.length + } else if (ArrayBuffer.isView(chunk)) { + // get length of ArrayBuffer + len = chunk.byteLength } else if (!generateETag && chunk.length < 1000) { // just calculate length when no ETag + small chunk len = Buffer.byteLength(chunk, encoding) diff --git a/test/res.send.js b/test/res.send.js index f38ffde9776..1d9beea3a9b 100644 --- a/test/res.send.js +++ b/test/res.send.js @@ -165,11 +165,9 @@ describe('res', function(){ describe('.send(Buffer)', function(){ it('should send as octet-stream', function(done){ var app = express(); - app.use(function(req, res){ res.send(Buffer.from('hello')) }); - request(app) .get('/') .expect(200) @@ -180,11 +178,9 @@ describe('res', function(){ it('should set ETag', function (done) { var app = express(); - app.use(function (req, res) { res.send(Buffer.alloc(999, '-')) }); - request(app) .get('/') .expect('ETag', 'W/"3e7-qPnkJ3CVdVhFJQvUBfF10TmVA7g"') @@ -193,11 +189,9 @@ describe('res', function(){ it('should not override Content-Type', function(done){ var app = express(); - app.use(function(req, res){ res.set('Content-Type', 'text/plain').send(Buffer.from('hey')) }); - request(app) .get('/') .expect('Content-Type', 'text/plain; charset=utf-8') @@ -210,20 +204,34 @@ describe('res', function(){ const encodedHey = new TextEncoder().encode("hey"); res.set("Content-Type", "text/plain").send(encodedHey); }) - request(app) .get("/") .expect("Content-Type", "text/plain; charset=utf-8") .expect(200, "hey", done); }) + it('should handle a raw ArrayBuffer as binary data, not JSON', function(done){ + var app = express(); + app.use(function(req, res){ + const arrayBuffer = new ArrayBuffer(3); + const view = new Uint8Array(arrayBuffer); + view.set([10, 20, 30]); + res.send(arrayBuffer); + }); + request(app) + .get('/') + .expect(200) + .expect('Content-Type', 'application/octet-stream') + .expect(utils.shouldHaveBody(Buffer.from([10, 20, 30]))) + .expect('Content-Length', "3") + .end(done); + }) + it('should not override ETag', function (done) { var app = express() - app.use(function (req, res) { res.type('text/plain').set('ETag', '"foo"').send(Buffer.from('hey')) }) - request(app) .get('/') .expect('ETag', '"foo"')