Skip to content

Commit

Permalink
fix: HTTP2 tweaks (nodejs#2711)
Browse files Browse the repository at this point in the history
Co-authored-by: Khafra <[email protected]>
  • Loading branch information
2 people authored and crysmags committed Feb 21, 2024
1 parent 12d1604 commit 88876f3
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 3 deletions.
23 changes: 21 additions & 2 deletions lib/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -808,6 +808,7 @@ class Parser {
.removeListener('close', onSocketClose)

client[kSocket] = null
client[kHTTP2Session] = null
client[kQueue][client[kRunningIdx]++] = null
client.emit('disconnect', client[kUrl], [client], new InformationalError('upgrade'))

Expand Down Expand Up @@ -1421,7 +1422,7 @@ function _resume (client, sync) {
return
}

if (!socket && !client[kHTTP2Session]) {
if (!socket) {
connect(client)
return
}
Expand Down Expand Up @@ -1796,7 +1797,25 @@ function writeH2 (client, session, request) {
})

stream.once('end', () => {
request.onComplete([])
// When state is null, it means we haven't consumed body and the stream still do not have
// a state.
// Present specially when using pipeline or stream
if (stream.state?.state == null || stream.state.state < 6) {
request.onComplete([])
return
}

// Stream is closed or half-closed-remote (6), decrement counter and cleanup
// It does not have sense to continue working with the stream as we do not
// have yet RST_STREAM support on client-side
h2State.openStreams -= 1
if (h2State.openStreams === 0) {
session.unref()
}

const err = new InformationalError('HTTP/2: stream half-closed (remote)')
errorRequest(client, request, err)
util.destroy(stream, err)
})

stream.on('data', (chunk) => {
Expand Down
32 changes: 31 additions & 1 deletion test/http2.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const { Client, Agent } = require('..')

const isGreaterThanv20 = process.versions.node.split('.').map(Number)[0] >= 20

plan(24)
plan(25)

test('Should support H2 connection', async t => {
const body = []
Expand Down Expand Up @@ -1243,3 +1243,33 @@ test('The h2 pseudo-headers is not included in the headers', async t => {
t.equal(response.statusCode, 200)
t.equal(response.headers[':status'], undefined)
})

test('Should throw informational error on half-closed streams (remote)', async t => {
const server = createSecureServer(pem)

server.on('stream', (stream, headers) => {
stream.destroy()
})

server.listen(0)
await once(server, 'listening')

const client = new Client(`https://localhost:${server.address().port}`, {
connect: {
rejectUnauthorized: false
},
allowH2: true
})

t.plan(2)
t.teardown(server.close.bind(server))
t.teardown(client.close.bind(client))

await client.request({
path: '/',
method: 'GET'
}).catch(err => {
t.equal(err.message, 'HTTP/2: stream half-closed (remote)')
t.equal(err.code, 'UND_ERR_INFO')
})
})

0 comments on commit 88876f3

Please sign in to comment.