Skip to content

Commit

Permalink
fix: setEncoding should not throw on body nodejs#1125
Browse files Browse the repository at this point in the history
  • Loading branch information
Uzlopak committed Aug 25, 2024
1 parent ee45443 commit 6ff7c1a
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 8 deletions.
31 changes: 24 additions & 7 deletions lib/api/readable.js
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,17 @@ class BodyReadable extends Readable {
.resume()
})
}

/**
* @param {BufferEncoding} encoding
* @returns {BodyReadable}
*/
setEncoding (encoding) {
if (Buffer.isEncoding(encoding)) {
this._readableState.encoding = encoding
}
return this
}
}

// https://streams.spec.whatwg.org/#readablestream-locked
Expand Down Expand Up @@ -278,10 +289,10 @@ function consumeStart (consume) {
}

if (state.endEmitted) {
consumeEnd(this[kConsume])
consumeEnd(this[kConsume], this._readableState.encoding)
} else {
consume.stream.on('end', function () {
consumeEnd(this[kConsume])
consumeEnd(this[kConsume], this._readableState.encoding)
})
}

Expand All @@ -295,8 +306,10 @@ function consumeStart (consume) {
/**
* @param {Buffer[]} chunks
* @param {number} length
* @param {BufferEncoding} encoding
* @returns {string}
*/
function chunksDecode (chunks, length) {
function chunksDecode (chunks, length, encoding) {
if (chunks.length === 0 || length === 0) {
return ''
}
Expand All @@ -311,7 +324,11 @@ function chunksDecode (chunks, length) {
buffer[2] === 0xbf
? 3
: 0
return buffer.utf8Slice(start, bufferLength)
if (!encoding || encoding === 'utf8' || encoding === 'utf-8') {
return buffer.utf8Slice(start, bufferLength)
} else {
return buffer.subarray(start, bufferLength).toString(encoding)
}
}

/**
Expand Down Expand Up @@ -339,14 +356,14 @@ function chunksConcat (chunks, length) {
return buffer
}

function consumeEnd (consume) {
function consumeEnd (consume, encoding) {
const { type, body, resolve, stream, length } = consume

try {
if (type === 'text') {
resolve(chunksDecode(body, length))
resolve(chunksDecode(body, length, encoding))
} else if (type === 'json') {
resolve(JSON.parse(chunksDecode(body, length)))
resolve(JSON.parse(chunksDecode(body, length, encoding)))
} else if (type === 'arrayBuffer') {
resolve(chunksConcat(body, length).buffer)
} else if (type === 'blob') {
Expand Down
87 changes: 86 additions & 1 deletion test/client-request.js
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ test('request body destroyed on invalid callback', async (t) => {
after(() => client.destroy())

const body = new Readable({
read () {}
read () { }
})
try {
client.request({
Expand Down Expand Up @@ -1252,3 +1252,88 @@ test('request post body DataView', async (t) => {

await t.completed
})

test('request multibyte json with setEncoding', async (t) => {
t = tspl(t, { plan: 1 })

const asd = Buffer.from('あいうえお')
const data = JSON.stringify({ asd })
const server = createServer((req, res) => {
res.write(data.slice(0, 1))
setTimeout(() => {
res.write(data.slice(1))
res.end()
}, 100)
})
after(server.close.bind(server))

server.listen(0, async () => {
const client = new Client(`http://localhost:${server.address().port}`)
after(client.destroy.bind(client))

const { body } = await client.request({
path: '/',
method: 'GET'
})
body.setEncoding('utf8')
t.deepStrictEqual(JSON.parse(data), await body.json())
})

await t.completed
})

test('request multibyte text with setEncoding', async (t) => {
t = tspl(t, { plan: 1 })

const data = Buffer.from('あいうえお')
const server = createServer((req, res) => {
res.write(data.slice(0, 1))
setTimeout(() => {
res.write(data.slice(1))
res.end()
}, 100)
})
after(server.close.bind(server))

server.listen(0, async () => {
const client = new Client(`http://localhost:${server.address().port}`)
after(client.destroy.bind(client))

const { body } = await client.request({
path: '/',
method: 'GET'
})
body.setEncoding('utf8')
t.deepStrictEqual(data.toString('utf8'), await body.text())
})

await t.completed
})

test('request multibyte text with setEncoding', async (t) => {
t = tspl(t, { plan: 1 })

const data = Buffer.from('あいうえお')
const server = createServer((req, res) => {
res.write(data.slice(0, 1))
setTimeout(() => {
res.write(data.slice(1))
res.end()
}, 100)
})
after(server.close.bind(server))

server.listen(0, async () => {
const client = new Client(`http://localhost:${server.address().port}`)
after(client.destroy.bind(client))

const { body } = await client.request({
path: '/',
method: 'GET'
})
body.setEncoding('hex')
t.deepStrictEqual(data.toString('hex'), await body.text())
})

await t.completed
})

0 comments on commit 6ff7c1a

Please sign in to comment.