Skip to content

Commit 5fb6dc0

Browse files
authored
fix(HTTP/2): handle consumption of aborted request (#2387)
1 parent 30b2d91 commit 5fb6dc0

File tree

2 files changed

+89
-15
lines changed

2 files changed

+89
-15
lines changed

lib/client.js

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1658,19 +1658,6 @@ function writeH2 (client, session, request) {
16581658
return false
16591659
}
16601660

1661-
try {
1662-
// TODO(HTTP/2): Should we call onConnect immediately or on stream ready event?
1663-
request.onConnect((err) => {
1664-
if (request.aborted || request.completed) {
1665-
return
1666-
}
1667-
1668-
errorRequest(client, request, err || new RequestAbortedError())
1669-
})
1670-
} catch (err) {
1671-
errorRequest(client, request, err)
1672-
}
1673-
16741661
if (request.aborted) {
16751662
return false
16761663
}
@@ -1682,9 +1669,34 @@ function writeH2 (client, session, request) {
16821669
headers[HTTP2_HEADER_AUTHORITY] = host || client[kHost]
16831670
headers[HTTP2_HEADER_METHOD] = method
16841671

1672+
try {
1673+
// We are already connected, streams are pending.
1674+
// We can call on connect, and wait for abort
1675+
request.onConnect((err) => {
1676+
if (request.aborted || request.completed) {
1677+
return
1678+
}
1679+
1680+
err = err || new RequestAbortedError()
1681+
1682+
if (stream != null) {
1683+
util.destroy(stream, err)
1684+
1685+
h2State.openStreams -= 1
1686+
if (h2State.openStreams === 0) {
1687+
session.unref()
1688+
}
1689+
}
1690+
1691+
errorRequest(client, request, err)
1692+
})
1693+
} catch (err) {
1694+
errorRequest(client, request, err)
1695+
}
1696+
16851697
if (method === 'CONNECT') {
16861698
session.ref()
1687-
// we are already connected, streams are pending, first request
1699+
// We are already connected, streams are pending, first request
16881700
// will create a new stream. We trigger a request to create the stream and wait until
16891701
// `ready` event is triggered
16901702
// We disabled endStream to allow the user to write to the stream

test/fetch/http2.js

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ const { Client, fetch, Headers } = require('../..')
1313

1414
const nodeVersion = Number(process.version.split('v')[1].split('.')[0])
1515

16-
plan(7)
16+
plan(8)
1717

1818
test('[Fetch] Issue#2311', async t => {
1919
const expectedBody = 'hello from client!'
@@ -413,3 +413,65 @@ test('Issue#2415', async (t) => {
413413

414414
t.doesNotThrow(() => new Headers(response.headers))
415415
})
416+
417+
test('Issue #2386', async t => {
418+
const server = createSecureServer(pem)
419+
const body = Buffer.from('hello')
420+
const requestChunks = []
421+
const expectedResponseBody = { hello: 'h2' }
422+
const controller = new AbortController()
423+
const signal = controller.signal
424+
425+
server.on('stream', async (stream, headers) => {
426+
t.equal(headers[':method'], 'PUT')
427+
t.equal(headers[':path'], '/')
428+
t.equal(headers[':scheme'], 'https')
429+
430+
stream.on('data', chunk => requestChunks.push(chunk))
431+
432+
stream.respond({
433+
'content-type': 'application/json',
434+
'x-custom-h2': headers['x-my-header'],
435+
':status': 200
436+
})
437+
438+
stream.end(JSON.stringify(expectedResponseBody))
439+
})
440+
441+
t.plan(4)
442+
443+
server.listen(0)
444+
await once(server, 'listening')
445+
446+
const client = new Client(`https://localhost:${server.address().port}`, {
447+
connect: {
448+
rejectUnauthorized: false
449+
},
450+
allowH2: true
451+
})
452+
453+
t.teardown(server.close.bind(server))
454+
t.teardown(client.close.bind(client))
455+
456+
try {
457+
await fetch(
458+
`https://localhost:${server.address().port}/`,
459+
// Needs to be passed to disable the reject unauthorized
460+
{
461+
body,
462+
signal,
463+
method: 'PUT',
464+
dispatcher: client,
465+
headers: {
466+
'x-my-header': 'foo',
467+
'content-type': 'text-plain'
468+
}
469+
}
470+
)
471+
472+
controller.abort()
473+
t.pass()
474+
} catch (error) {
475+
t.error(error)
476+
}
477+
})

0 commit comments

Comments
 (0)