Skip to content

Commit

Permalink
fix: support ArrayBufferView and ArrayBuffer as body (nodejs#1584)
Browse files Browse the repository at this point in the history
* fix: support `ArrayBufferView` and `ArrayBuffer` as body

* test: ArrayBufferView as Request.body
  • Loading branch information
LiviaMedeiros authored and crysmags committed Feb 27, 2024
1 parent 2390868 commit 1dbee12
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 19 deletions.
14 changes: 7 additions & 7 deletions lib/fetch/body.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,16 +57,16 @@ function extractBody (object, keepalive = false) {

// Set Content-Type to `application/x-www-form-urlencoded;charset=UTF-8`.
contentType = 'application/x-www-form-urlencoded;charset=UTF-8'
} else if (isArrayBuffer(object) || ArrayBuffer.isView(object)) {
// BufferSource
} else if (isArrayBuffer(object)) {
// BufferSource/ArrayBuffer

if (object instanceof DataView) {
// TODO: Blob doesn't seem to work with DataView?
object = object.buffer
}
// Set source to a copy of the bytes held by object.
source = new Uint8Array(object.slice())
} else if (ArrayBuffer.isView(object)) {
// BufferSource/ArrayBufferView

// Set source to a copy of the bytes held by object.
source = new Uint8Array(object)
source = new Uint8Array(object.buffer.slice(object.byteOffset, object.byteOffset + object.byteLength))
} else if (util.isFormDataLike(object)) {
const boundary = '----formdata-undici-' + Math.random()
const prefix = `--${boundary}\r\nContent-Disposition: form-data`
Expand Down
16 changes: 16 additions & 0 deletions test/node-fetch/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -1032,6 +1032,22 @@ describe('node-fetch', () => {
})
})

it('should allow POST request with ArrayBufferView (BigUint64Array) body', () => {
const encoder = new TextEncoder()
const url = `${base}inspect`
const options = {
method: 'POST',
body: new BigUint64Array(encoder.encode('0123456789abcdef').buffer)
}
return fetch(url, options).then(res => res.json()).then(res => {
expect(res.method).to.equal('POST')
expect(res.body).to.equal('0123456789abcdef')
expect(res.headers['transfer-encoding']).to.be.undefined
expect(res.headers['content-type']).to.be.undefined
expect(res.headers['content-length']).to.equal('16')
})
})

it('should allow POST request with ArrayBufferView (DataView) body', () => {
const encoder = new TextEncoder()
const url = `${base}inspect`
Expand Down
34 changes: 28 additions & 6 deletions test/node-fetch/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -225,34 +225,56 @@ describe('Request', () => {

it('should support ArrayBuffer as body', () => {
const encoder = new TextEncoder()
const body = encoder.encode('a=12345678901234').buffer
const request = new Request(base, {
method: 'POST',
body: encoder.encode('a=1').buffer
body
})
new Uint8Array(body)[0] = 0
return request.text().then(result => {
expect(result).to.equal('a=1')
expect(result).to.equal('a=12345678901234')
})
})

it('should support Uint8Array as body', () => {
const encoder = new TextEncoder()
const fullbuffer = encoder.encode('a=12345678901234').buffer
const body = new Uint8Array(fullbuffer, 2, 9)
const request = new Request(base, {
method: 'POST',
body: encoder.encode('a=1')
body
})
body[0] = 0
return request.text().then(result => {
expect(result).to.equal('a=1')
expect(result).to.equal('123456789')
})
})

it('should support BigUint64Array as body', () => {
const encoder = new TextEncoder()
const fullbuffer = encoder.encode('a=12345678901234').buffer
const body = new BigUint64Array(fullbuffer, 8, 1)
const request = new Request(base, {
method: 'POST',
body
})
body[0] = 0n
return request.text().then(result => {
expect(result).to.equal('78901234')
})
})

it('should support DataView as body', () => {
const encoder = new TextEncoder()
const fullbuffer = encoder.encode('a=12345678901234').buffer
const body = new Uint8Array(fullbuffer, 2, 9)
const request = new Request(base, {
method: 'POST',
body: new DataView(encoder.encode('a=1').buffer)
body
})
body[0] = 0
return request.text().then(result => {
expect(result).to.equal('a=1')
expect(result).to.equal('123456789')
})
})
})
31 changes: 25 additions & 6 deletions test/node-fetch/response.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,11 @@ describe('Response', () => {

it('should support ArrayBuffer as body', () => {
const encoder = new TextEncoder()
const res = new Response(encoder.encode('a=1'))
const fullbuffer = encoder.encode('a=12345678901234').buffer
const res = new Response(fullbuffer)
new Uint8Array(fullbuffer)[0] = 0
return res.text().then(result => {
expect(result).to.equal('a=1')
expect(result).to.equal('a=12345678901234')
})
})

Expand All @@ -176,17 +178,34 @@ describe('Response', () => {

it('should support Uint8Array as body', () => {
const encoder = new TextEncoder()
const res = new Response(encoder.encode('a=1'))
const fullbuffer = encoder.encode('a=12345678901234').buffer
const body = new Uint8Array(fullbuffer, 2, 9)
const res = new Response(body)
body[0] = 0
return res.text().then(result => {
expect(result).to.equal('a=1')
expect(result).to.equal('123456789')
})
})

it('should support BigUint64Array as body', () => {
const encoder = new TextEncoder()
const fullbuffer = encoder.encode('a=12345678901234').buffer
const body = new BigUint64Array(fullbuffer, 8, 1)
const res = new Response(body)
body[0] = 0n
return res.text().then(result => {
expect(result).to.equal('78901234')
})
})

it('should support DataView as body', () => {
const encoder = new TextEncoder()
const res = new Response(new DataView(encoder.encode('a=1').buffer))
const fullbuffer = encoder.encode('a=12345678901234').buffer
const body = new Uint8Array(fullbuffer, 2, 9)
const res = new Response(body)
body[0] = 0
return res.text().then(result => {
expect(result).to.equal('a=1')
expect(result).to.equal('123456789')
})
})

Expand Down

0 comments on commit 1dbee12

Please sign in to comment.