diff options
author | Rano | Ranadeep <ranadip.bswas@gmail.com> | 2024-07-15 13:40:59 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-07-15 17:10:59 +0530 |
commit | 702f7ee89c882f82b2fb649212bd8dbbb4476062 (patch) | |
tree | 95dbfcaebbd13fd614730da656d1dc49524c0fcc /ext/node/ops/http2.rs | |
parent | 9128cc98504676a9142869743d6ab1dc319da2ce (diff) |
fix(std/http2): release window capacity back to remote stream (#24576)
This PR adds logic to release window capacity after reading the chunks
from the stream. Without it, large response (more than `u16::MAX`) may
fill up the capacity and the whole response can't be read.
Closes https://github.com/denoland/deno/issues/24552
Closes https://github.com/denoland/deno/issues/24305
Diffstat (limited to 'ext/node/ops/http2.rs')
-rw-r--r-- | ext/node/ops/http2.rs | 29 |
1 files changed, 13 insertions, 16 deletions
diff --git a/ext/node/ops/http2.rs b/ext/node/ops/http2.rs index d12e108e6..d877a5b14 100644 --- a/ext/node/ops/http2.rs +++ b/ext/node/ops/http2.rs @@ -456,24 +456,21 @@ fn poll_data_or_trailers( cx: &mut std::task::Context, body: &mut RecvStream, ) -> Poll<Result<DataOrTrailers, h2::Error>> { - loop { - if let Poll::Ready(trailers) = body.poll_trailers(cx) { - if let Some(trailers) = trailers? { - return Poll::Ready(Ok(DataOrTrailers::Trailers(trailers))); - } else { - return Poll::Ready(Ok(DataOrTrailers::Eof)); - } - } - if let Poll::Ready(data) = body.poll_data(cx) { - if let Some(data) = data { - return Poll::Ready(Ok(DataOrTrailers::Data(data?))); - } - // If data is None, loop one more time to check for trailers - continue; + if let Poll::Ready(trailers) = body.poll_trailers(cx) { + if let Some(trailers) = trailers? { + return Poll::Ready(Ok(DataOrTrailers::Trailers(trailers))); + } else { + return Poll::Ready(Ok(DataOrTrailers::Eof)); } - // Return pending here as poll_data will keep the waker - return Poll::Pending; } + if let Poll::Ready(Some(data)) = body.poll_data(cx) { + let data = data?; + body.flow_control().release_capacity(data.len())?; + return Poll::Ready(Ok(DataOrTrailers::Data(data))); + // If `poll_data` returns `Ready(None)`, poll one more time to check for trailers + } + // Return pending here as poll_data will keep the waker + Poll::Pending } #[op2(async)] |