Skip to content

Commit c0cf8bb

Browse files
committed
fix: handle consumption of aborted request
1 parent 039fa15 commit c0cf8bb

File tree

2 files changed

+66
-0
lines changed

2 files changed

+66
-0
lines changed

lib/client.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1805,6 +1805,11 @@ function writeH2 (client, session, request) {
18051805
})
18061806

18071807
stream.on('data', (chunk) => {
1808+
// Aborting a request does not abort
1809+
// the stream, so we need to check and destroy it if request
1810+
// is aborted.
1811+
if (request.aborted) util.destroy(stream, new RequestAbortedError())
1812+
18081813
if (request.onData(chunk) === false) stream.pause()
18091814
})
18101815

test/fetch/http2.js

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,3 +413,64 @@ 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(3)
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+
} catch (error) {
474+
t.error(error)
475+
}
476+
})

0 commit comments

Comments
 (0)