Skip to content

Commit 4b1c09d

Browse files
authored
fix(network): preserve chunked request boundaries (#3530)
* fix(network): preserve chunked request boundaries Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * fix(network): bound chunk framing amplification Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * fix(supervisor): box sandbox runtime future Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * fix(network): buffer chunked relay read-ahead Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * fix(network): flush completed chunks promptly Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> --------- Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com>
1 parent 718dba3 commit 4b1c09d

3 files changed

Lines changed: 392 additions & 29 deletions

File tree

‎crates/openshell-supervisor-network/src/l7/relay.rs‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ use std::sync::Arc;
3535
use tokio::io::{AsyncRead, AsyncWrite, AsyncWriteExt};
3636
use tracing::{debug, warn};
3737

38+
const CONNECTION_READ_AHEAD_BYTES: usize = 8 * 1024;
39+
3840
/// Context for L7 request policy evaluation.
3941
#[derive(Clone)]
4042
#[cfg_attr(test, derive(Default))]
@@ -754,6 +756,17 @@ where
754756
C: AsyncRead + AsyncWrite + Unpin + Send,
755757
U: AsyncRead + AsyncWrite + Unpin + Send,
756758
{
759+
// Keep read-ahead state for the lifetime of the inspected connection. An
760+
// HTTP parser may fetch bytes from the next pipelined request while
761+
// finishing the current one; retaining them here ensures the next request
762+
// still passes through its own policy decision.
763+
let mut client_buffer =
764+
tokio::io::BufReader::with_capacity(CONNECTION_READ_AHEAD_BYTES, client);
765+
let mut upstream_buffer =
766+
tokio::io::BufReader::with_capacity(CONNECTION_READ_AHEAD_BYTES, upstream);
767+
let client = &mut client_buffer;
768+
let upstream = &mut upstream_buffer;
769+
757770
match config.protocol {
758771
L7Protocol::Rest | L7Protocol::Websocket => {
759772
relay_rest(config, &engine, client, upstream, ctx).await
@@ -813,6 +826,15 @@ where
813826
C: AsyncRead + AsyncWrite + Unpin + Send,
814827
U: AsyncRead + AsyncWrite + Unpin + Send,
815828
{
829+
// Route selection also owns the full keep-alive loop, so buffered bytes
830+
// remain available across per-request parsing and authorization.
831+
let mut client_buffer =
832+
tokio::io::BufReader::with_capacity(CONNECTION_READ_AHEAD_BYTES, client);
833+
let mut upstream_buffer =
834+
tokio::io::BufReader::with_capacity(CONNECTION_READ_AHEAD_BYTES, upstream);
835+
let client = &mut client_buffer;
836+
let upstream = &mut upstream_buffer;
837+
816838
let provider =
817839
crate::l7::rest::RestProvider::with_options(crate::l7::path::CanonicalizeOptions {
818840
allow_encoded_slash: configs.iter().any(|config| config.allow_encoded_slash),

0 commit comments

Comments
 (0)