Skip to content

Commit 1335ea8

Browse files
committed
fix: finish paused HTTP/1 parser on socket end
Signed-off-by: marko1olo <barsukdana@gmail.com>
1 parent 313f4e0 commit 1335ea8

2 files changed

Lines changed: 52 additions & 1 deletion

File tree

lib/dispatcher/client-h1.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -371,10 +371,14 @@ class Parser {
371371
finish () {
372372
assert(currentParser === null)
373373
assert(this.ptr != null)
374-
assert(!this.paused)
375374

376375
const { llhttp } = this
377376

377+
if (this.paused) {
378+
llhttp.llhttp_resume(this.ptr)
379+
this.paused = false
380+
}
381+
378382
let ret
379383

380384
try {

test/client.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
const { tspl } = require('@matteo.collina/tspl')
44
const { readFileSync, createReadStream } = require('node:fs')
55
const { createServer } = require('node:http')
6+
const { createServer: createNetServer } = require('node:net')
67
const { Readable, PassThrough } = require('node:stream')
78
const { test, after } = require('node:test')
89
const { Client, errors } = require('..')
@@ -1190,6 +1191,52 @@ test('ignore request header mutations', async (t) => {
11901191
await t.completed
11911192
})
11921193

1194+
test('socket end completes response when body is paused by backpressure', async (t) => {
1195+
t = tspl(t, { plan: 2 })
1196+
1197+
const payload = Buffer.from('aa')
1198+
const server = createNetServer((socket) => {
1199+
socket.once('data', () => {
1200+
socket.write(
1201+
'HTTP/1.1 200 OK\r\n' +
1202+
`Content-Length: ${payload.length}\r\n` +
1203+
'Connection: close\r\n\r\n'
1204+
)
1205+
socket.write(payload)
1206+
socket.end()
1207+
})
1208+
})
1209+
after(() => server.close())
1210+
1211+
server.listen(0, '127.0.0.1', () => {
1212+
const client = new Client(`http://127.0.0.1:${server.address().port}`)
1213+
after(() => client.close())
1214+
1215+
client.request({
1216+
path: '/',
1217+
method: 'GET',
1218+
highWaterMark: 1
1219+
}, (err, data) => {
1220+
t.ifError(err)
1221+
1222+
let body = ''
1223+
data.body.setEncoding('utf8')
1224+
data.body.on('data', (chunk) => {
1225+
body += chunk
1226+
})
1227+
data.body.on('end', () => {
1228+
t.strictEqual(body, payload.toString())
1229+
})
1230+
1231+
setImmediate(() => {
1232+
data.body.resume()
1233+
})
1234+
})
1235+
})
1236+
1237+
await t.completed
1238+
})
1239+
11931240
test('url-like url', async (t) => {
11941241
t = tspl(t, { plan: 1 })
11951242

0 commit comments

Comments
 (0)