Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: support TypedArray and DataView as Request body #1472

Merged
merged 2 commits into from Jun 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 4 additions & 5 deletions lib/core/request.js
Expand Up @@ -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)) {
Expand Down
209 changes: 209 additions & 0 deletions test/client-request.js
Expand Up @@ -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()
})
})