diff --git a/lib/core/request.js b/lib/core/request.js index 2a13b0549a8..bbbac106833 100644 --- a/lib/core/request.js +++ b/lib/core/request.js @@ -80,13 +80,12 @@ class Request { this.body = null } else if (util.isStream(body)) { this.body = body - } else if (body instanceof DataView) { - // TODO: Why is DataView special? - this.body = body.buffer.byteLength ? Buffer.from(body.buffer) : null - } else if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) { - this.body = body.byteLength ? Buffer.from(body) : null } else if (util.isBuffer(body)) { this.body = body.byteLength ? body : null + } else if (ArrayBuffer.isView(body)) { + this.body = body.buffer.byteLength ? Buffer.from(body.buffer, body.byteOffset, body.byteLength) : null + } else if (body instanceof ArrayBuffer) { + this.body = body.byteLength ? Buffer.from(body) : null } else if (typeof body === 'string') { this.body = body.length ? Buffer.from(body) : null } else if (util.isFormDataLike(body) || util.isIterable(body) || util.isBlobLike(body)) { diff --git a/test/client-request.js b/test/client-request.js index bce9644f106..74976bb5925 100644 --- a/test/client-request.js +++ b/test/client-request.js @@ -727,3 +727,212 @@ test('request with FormData body on node < 16', { skip: nodeMajor >= 16 }, async body: fd }), errors.InvalidArgumentError) }) + +test('request post body Buffer from string', (t) => { + t.plan(2) + const requestBody = Buffer.from('abcdefghijklmnopqrstuvwxyz') + + const server = createServer(async (req, res) => { + let ret = '' + for await (const chunk of req) { + ret += chunk + } + t.equal(ret, 'abcdefghijklmnopqrstuvwxyz') + res.end() + }) + t.teardown(server.close.bind(server)) + + server.listen(0, async () => { + const client = new Client(`http://localhost:${server.address().port}`) + t.teardown(client.destroy.bind(client)) + + const { body } = await client.request({ + path: '/', + method: 'POST', + body: requestBody, + maxRedirections: 2 + }) + await body.text() + t.pass() + }) +}) + +test('request post body Buffer from buffer', (t) => { + t.plan(2) + const fullBuffer = new TextEncoder().encode('abcdefghijklmnopqrstuvwxyz') + const requestBody = Buffer.from(fullBuffer.buffer, 8, 16) + + const server = createServer(async (req, res) => { + let ret = '' + for await (const chunk of req) { + ret += chunk + } + t.equal(ret, 'ijklmnopqrstuvwx') + res.end() + }) + t.teardown(server.close.bind(server)) + + server.listen(0, async () => { + const client = new Client(`http://localhost:${server.address().port}`) + t.teardown(client.destroy.bind(client)) + + const { body } = await client.request({ + path: '/', + method: 'POST', + body: requestBody, + maxRedirections: 2 + }) + await body.text() + t.pass() + }) +}) + +test('request post body Uint8Array', (t) => { + t.plan(2) + const fullBuffer = new TextEncoder().encode('abcdefghijklmnopqrstuvwxyz') + const requestBody = new Uint8Array(fullBuffer.buffer, 8, 16) + + const server = createServer(async (req, res) => { + let ret = '' + for await (const chunk of req) { + ret += chunk + } + t.equal(ret, 'ijklmnopqrstuvwx') + res.end() + }) + t.teardown(server.close.bind(server)) + + server.listen(0, async () => { + const client = new Client(`http://localhost:${server.address().port}`) + t.teardown(client.destroy.bind(client)) + + const { body } = await client.request({ + path: '/', + method: 'POST', + body: requestBody, + maxRedirections: 2 + }) + await body.text() + t.pass() + }) +}) + +test('request post body Uint32Array', (t) => { + t.plan(2) + const fullBuffer = new TextEncoder().encode('abcdefghijklmnopqrstuvwxyz') + const requestBody = new Uint32Array(fullBuffer.buffer, 8, 4) + + const server = createServer(async (req, res) => { + let ret = '' + for await (const chunk of req) { + ret += chunk + } + t.equal(ret, 'ijklmnopqrstuvwx') + res.end() + }) + t.teardown(server.close.bind(server)) + + server.listen(0, async () => { + const client = new Client(`http://localhost:${server.address().port}`) + t.teardown(client.destroy.bind(client)) + + const { body } = await client.request({ + path: '/', + method: 'POST', + body: requestBody, + maxRedirections: 2 + }) + await body.text() + t.pass() + }) +}) + +test('request post body Float64Array', (t) => { + t.plan(2) + const fullBuffer = new TextEncoder().encode('abcdefghijklmnopqrstuvwxyz') + const requestBody = new Float64Array(fullBuffer.buffer, 8, 2) + + const server = createServer(async (req, res) => { + let ret = '' + for await (const chunk of req) { + ret += chunk + } + t.equal(ret, 'ijklmnopqrstuvwx') + res.end() + }) + t.teardown(server.close.bind(server)) + + server.listen(0, async () => { + const client = new Client(`http://localhost:${server.address().port}`) + t.teardown(client.destroy.bind(client)) + + const { body } = await client.request({ + path: '/', + method: 'POST', + body: requestBody, + maxRedirections: 2 + }) + await body.text() + t.pass() + }) +}) + +test('request post body BigUint64Array', (t) => { + t.plan(2) + const fullBuffer = new TextEncoder().encode('abcdefghijklmnopqrstuvwxyz') + const requestBody = new BigUint64Array(fullBuffer.buffer, 8, 2) + + const server = createServer(async (req, res) => { + let ret = '' + for await (const chunk of req) { + ret += chunk + } + t.equal(ret, 'ijklmnopqrstuvwx') + res.end() + }) + t.teardown(server.close.bind(server)) + + server.listen(0, async () => { + const client = new Client(`http://localhost:${server.address().port}`) + t.teardown(client.destroy.bind(client)) + + const { body } = await client.request({ + path: '/', + method: 'POST', + body: requestBody, + maxRedirections: 2 + }) + await body.text() + t.pass() + }) +}) + +test('request post body DataView', (t) => { + t.plan(2) + const fullBuffer = new TextEncoder().encode('abcdefghijklmnopqrstuvwxyz') + const requestBody = new DataView(fullBuffer.buffer, 8, 16) + + const server = createServer(async (req, res) => { + let ret = '' + for await (const chunk of req) { + ret += chunk + } + t.equal(ret, 'ijklmnopqrstuvwx') + res.end() + }) + t.teardown(server.close.bind(server)) + + server.listen(0, async () => { + const client = new Client(`http://localhost:${server.address().port}`) + t.teardown(client.destroy.bind(client)) + + const { body } = await client.request({ + path: '/', + method: 'POST', + body: requestBody, + maxRedirections: 2 + }) + await body.text() + t.pass() + }) +})