Skip to content

[9.4] [Core] Fix KibanaRequest aborted$ never emitting for HTTP/2 requests (#285244) - #285382

Merged
kibanamachine merged 1 commit into
elastic:9.4from
kibanamachine:backport/9.4/pr-285244
Aug 17, 2026
Merged

[9.4] [Core] Fix KibanaRequest aborted$ never emitting for HTTP/2 requests (#285244)#285382
kibanamachine merged 1 commit into
elastic:9.4from
kibanamachine:backport/9.4/pr-285244

Conversation

@kibanamachine

Copy link
Copy Markdown
Contributor

Backport

This will backport the following commits from main to 9.4:

Questions ?

Please refer to the Backport tool documentation

…lastic#285244)

## Human summary

Improves the detection of completed requests by additionally checking
for `res.writableEnded`. This works around a quirk in Node.js when
running in http/2, which is resolved in 26+:
nodejs/node#63249.

Checking for `res.writableEnded` does not change anything when running
in http/1, as this is always true when `res.writableFinished`. This
changes behavior for http/2 by properly detecting aborted requests.

This should result in downstream consumers having a more reliable signal
for when a client request is aborted, allowing them to cancel jobs such
as in-flight ES requests regardless of http protocol.

We detected this while writing scout tests for
elastic#285153

## AI description
When an HTTP/2 client destroys a stream mid-request (RST_STREAM /
NGHTTP2_CANCEL, e.g. an AbortController cancel or browser navigation),
Node's Http2ServerResponse emits 'close' with writableFinished === true
even though nothing was written. isCompleted() relied on
writableFinished alone, so the !isCompleted filter swallowed the event
and request.events.aborted$ never fired — consumers (route handlers,
auth providers) could not observe HTTP/2 client aborts. HTTP/1 was
unaffected because writableFinished stays false there.

Treat a request as completed only when writableFinished &&
writableEnded: writableEnded only becomes true once the server actually
ended the response, and is truthful on both protocols and for abrupt
TCP-level disconnects.

Adds integration coverage in http2_protocol.test.ts driving a real
HTTP/2 TLS session that resets the stream while the handler is pending,
plus a control test asserting completed$ (and not aborted$) on normal
completion.

Co-authored-by: Claude Fable 5 <[email protected]>
(cherry picked from commit a19e27a)
@kibanamachine kibanamachine added the backport This PR is a backport of another PR label Aug 17, 2026
@kibanamachine
kibanamachine enabled auto-merge (squash) August 17, 2026 12:07
@kibanamachine

Copy link
Copy Markdown
Contributor Author

💚 Build Succeeded

Metrics [docs]

✅ unchanged

cc @legrego

@kibanamachine
kibanamachine merged commit 8cb7c7f into elastic:9.4 Aug 17, 2026
56 checks passed
legrego added a commit that referenced this pull request Aug 19, 2026
…quests (#285244) (#285403)

# Backport

This will backport the following commits from `main` to `8.19`:
- [[Core] Fix KibanaRequest aborted$ never emitting for HTTP/2 requests
(#285244)](#285244)

<!--- Backport version: 11.0.2 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sorenlouv/backport)

<!--BACKPORT [{"author":{"name":"Larry
Gregory","email":"[email protected]"},"sourceCommit":{"committedDate":"2026-08-17T11:55:38Z","message":"[Core]
Fix KibanaRequest aborted$ never emitting for HTTP/2 requests
(#285244)\n\n## Human summary\n\nImproves the detection of completed
requests by additionally checking\nfor `res.writableEnded`. This works
around a quirk in Node.js when\nrunning in http/2, which is resolved in
26+:\nhttps://github.com/nodejs/node/pull/63249.\n\nChecking for
`res.writableEnded` does not change anything when running\nin http/1, as
this is always true when `res.writableFinished`. This\nchanges behavior
for http/2 by properly detecting aborted requests.\n\nThis should result
in downstream consumers having a more reliable signal\nfor when a client
request is aborted, allowing them to cancel jobs such\nas in-flight ES
requests regardless of http protocol.\n\nWe detected this while writing
scout tests for\nhttps://github.com//pull/285153\n\n## AI
description\nWhen an HTTP/2 client destroys a stream mid-request
(RST_STREAM /\nNGHTTP2_CANCEL, e.g. an AbortController cancel or browser
navigation),\nNode's Http2ServerResponse emits 'close' with
writableFinished === true\neven though nothing was written.
isCompleted() relied on\nwritableFinished alone, so the !isCompleted
filter swallowed the event\nand request.events.aborted$ never fired —
consumers (route handlers,\nauth providers) could not observe HTTP/2
client aborts. HTTP/1 was\nunaffected because writableFinished stays
false there.\n\nTreat a request as completed only when writableFinished
&&\nwritableEnded: writableEnded only becomes true once the server
actually\nended the response, and is truthful on both protocols and for
abrupt\nTCP-level disconnects.\n\nAdds integration coverage in
http2_protocol.test.ts driving a real\nHTTP/2 TLS session that resets
the stream while the handler is pending,\nplus a control test asserting
completed$ (and not aborted$) on normal\ncompletion.\n\nCo-authored-by:
Claude Fable 5
<[email protected]>","sha":"a19e27a5dc885a40a31998f728c450d8aee27289","branchLabelMapping":{"^v9.6.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["Team:Security","release_note:skip","backport:all-open","v9.6.0","v9.4.6","v9.5.2"],"title":"[Core]
Fix KibanaRequest aborted$ never emitting for HTTP/2
requests","number":285244,"url":"https://github.com/elastic/kibana/pull/285244","mergeCommit":{"message":"[Core]
Fix KibanaRequest aborted$ never emitting for HTTP/2 requests
(#285244)\n\n## Human summary\n\nImproves the detection of completed
requests by additionally checking\nfor `res.writableEnded`. This works
around a quirk in Node.js when\nrunning in http/2, which is resolved in
26+:\nhttps://github.com/nodejs/node/pull/63249.\n\nChecking for
`res.writableEnded` does not change anything when running\nin http/1, as
this is always true when `res.writableFinished`. This\nchanges behavior
for http/2 by properly detecting aborted requests.\n\nThis should result
in downstream consumers having a more reliable signal\nfor when a client
request is aborted, allowing them to cancel jobs such\nas in-flight ES
requests regardless of http protocol.\n\nWe detected this while writing
scout tests for\nhttps://github.com//pull/285153\n\n## AI
description\nWhen an HTTP/2 client destroys a stream mid-request
(RST_STREAM /\nNGHTTP2_CANCEL, e.g. an AbortController cancel or browser
navigation),\nNode's Http2ServerResponse emits 'close' with
writableFinished === true\neven though nothing was written.
isCompleted() relied on\nwritableFinished alone, so the !isCompleted
filter swallowed the event\nand request.events.aborted$ never fired —
consumers (route handlers,\nauth providers) could not observe HTTP/2
client aborts. HTTP/1 was\nunaffected because writableFinished stays
false there.\n\nTreat a request as completed only when writableFinished
&&\nwritableEnded: writableEnded only becomes true once the server
actually\nended the response, and is truthful on both protocols and for
abrupt\nTCP-level disconnects.\n\nAdds integration coverage in
http2_protocol.test.ts driving a real\nHTTP/2 TLS session that resets
the stream while the handler is pending,\nplus a control test asserting
completed$ (and not aborted$) on normal\ncompletion.\n\nCo-authored-by:
Claude Fable 5
<[email protected]>","sha":"a19e27a5dc885a40a31998f728c450d8aee27289"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v9.6.0","branchLabelMappingKey":"^v9.6.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/285244","number":285244,"mergeCommit":{"message":"[Core]
Fix KibanaRequest aborted$ never emitting for HTTP/2 requests
(#285244)\n\n## Human summary\n\nImproves the detection of completed
requests by additionally checking\nfor `res.writableEnded`. This works
around a quirk in Node.js when\nrunning in http/2, which is resolved in
26+:\nhttps://github.com/nodejs/node/pull/63249.\n\nChecking for
`res.writableEnded` does not change anything when running\nin http/1, as
this is always true when `res.writableFinished`. This\nchanges behavior
for http/2 by properly detecting aborted requests.\n\nThis should result
in downstream consumers having a more reliable signal\nfor when a client
request is aborted, allowing them to cancel jobs such\nas in-flight ES
requests regardless of http protocol.\n\nWe detected this while writing
scout tests for\nhttps://github.com//pull/285153\n\n## AI
description\nWhen an HTTP/2 client destroys a stream mid-request
(RST_STREAM /\nNGHTTP2_CANCEL, e.g. an AbortController cancel or browser
navigation),\nNode's Http2ServerResponse emits 'close' with
writableFinished === true\neven though nothing was written.
isCompleted() relied on\nwritableFinished alone, so the !isCompleted
filter swallowed the event\nand request.events.aborted$ never fired —
consumers (route handlers,\nauth providers) could not observe HTTP/2
client aborts. HTTP/1 was\nunaffected because writableFinished stays
false there.\n\nTreat a request as completed only when writableFinished
&&\nwritableEnded: writableEnded only becomes true once the server
actually\nended the response, and is truthful on both protocols and for
abrupt\nTCP-level disconnects.\n\nAdds integration coverage in
http2_protocol.test.ts driving a real\nHTTP/2 TLS session that resets
the stream while the handler is pending,\nplus a control test asserting
completed$ (and not aborted$) on normal\ncompletion.\n\nCo-authored-by:
Claude Fable 5
<[email protected]>","sha":"a19e27a5dc885a40a31998f728c450d8aee27289"}},{"branch":"9.4","label":"v9.4.6","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"url":"https://github.com/elastic/kibana/pull/285382","number":285382,"state":"MERGED","mergeCommit":{"sha":"8cb7c7f6e2b21af321412223579d0eab0f0b8134","message":"[9.4]
[Core] Fix KibanaRequest aborted$ never emitting for HTTP/2 requests
(#285244) (#285382)\n\n# Backport\n\nThis will backport the following
commits from `main` to `9.4`:\n- [[Core] Fix KibanaRequest aborted$
never emitting for HTTP/2
requests\n(#285244)](https://github.com/elastic/kibana/pull/285244)\n\n\n\n###
Questions ?\nPlease refer to the [Backport
tool\ndocumentation](https://github.com/sorenlouv/backport)\n\n\n\nCo-authored-by:
Larry Gregory <[email protected]>\nCo-authored-by: Claude Fable 5
<[email protected]>"}},{"branch":"9.5","label":"v9.5.2","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"url":"https://github.com/elastic/kibana/pull/285383","number":285383,"state":"MERGED","mergeCommit":{"sha":"aeff16c0cbf64223297cf496f698e03a793c24bf","message":"[9.5]
[Core] Fix KibanaRequest aborted$ never emitting for HTTP/2 requests
(#285244) (#285383)\n\n# Backport\n\nThis will backport the following
commits from `main` to `9.5`:\n- [[Core] Fix KibanaRequest aborted$
never emitting for HTTP/2
requests\n(#285244)](https://github.com/elastic/kibana/pull/285244)\n\n\n\n###
Questions ?\nPlease refer to the [Backport
tool\ndocumentation](https://github.com/sorenlouv/backport)\n\n\n\nCo-authored-by:
Larry Gregory <[email protected]>\nCo-authored-by: Claude Fable 5
<[email protected]>"}}]}] BACKPORT-->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport This PR is a backport of another PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants