pub enum BufferedBody<B>where
B: HttpBody,{
Complete(Option<Bytes>),
Partial(PartialBufferedBody<B>),
Passthrough(B),
}Expand description
A body wrapper that represents different consumption states.
This enum allows predicates to partially consume request or response bodies without losing data. The complete body (including any buffered prefix) is forwarded to upstream services.
§States
Complete: Body fully buffered in memoryPartial: Prefix buffered, remaining stream preservedPassthrough: Untouched, zero overhead
§Examples
Creating a passthrough body for a new request:
use bytes::Bytes;
use http_body_util::Empty;
use hitbox_http::BufferedBody;
let body: BufferedBody<Empty<Bytes>> = BufferedBody::Passthrough(Empty::new());Creating a complete body from cached data:
use bytes::Bytes;
use http_body_util::Empty;
use hitbox_http::BufferedBody;
let cached_data = Bytes::from_static(b"{\"id\": 42}");
let body: BufferedBody<Empty<Bytes>> = BufferedBody::Complete(Some(cached_data));§State Transitions
Passthrough ──collect_exact()──► Partial (if stream continues)
│ │
│ ▼
└──────collect()──────────► CompleteVariants§
Complete(Option<Bytes>)
Body was fully read and buffered (within size limits).
The Option is used to yield the data once, then return None on subsequent polls.
Partial(PartialBufferedBody<B>)
Body was partially read - contains buffered prefix and remaining stream.
The PartialBufferedBody handles streaming of both the prefix and remaining data.
Passthrough(B)
Body was passed through without reading (untouched).
The body is forwarded directly to upstream without any buffering.
Implementations§
Source§impl<B> BufferedBody<B>where
B: HttpBody,
Internal result type for the low-level stream collection function.
impl<B> BufferedBody<B>where
B: HttpBody,
Internal result type for the low-level stream collection function.
Sourcepub async fn collect(self) -> Result<Bytes, Self>
pub async fn collect(self) -> Result<Bytes, Self>
Collects the entire body into memory.
Consumes all remaining bytes from the stream and returns them as a
contiguous Bytes buffer.
§Examples
use hitbox_http::BufferedBody;
async fn example<B: hyper::body::Body>(body: BufferedBody<B>)
where
B::Data: Send,
{
match body.collect().await {
Ok(bytes) => println!("Collected {} bytes", bytes.len()),
Err(error_body) => {
// Error occurred, but we still have the body for forwarding
}
}
}§Errors
Returns Err(BufferedBody::Partial(...)) if the underlying stream
yields an error. The error is preserved in the returned body so it
can be forwarded to upstream services.
§Performance
Allocates a buffer to hold the entire body. For large bodies, consider:
- Using
collect_exactto read only a prefix - Streaming the body directly without buffering
§Caveats
This method blocks until the entire body is received. For very large bodies or slow streams, this may take significant time and memory.
Sourcepub async fn collect_exact(self, limit_bytes: usize) -> CollectExactResult<B>where
B: Unpin,
pub async fn collect_exact(self, limit_bytes: usize) -> CollectExactResult<B>where
B: Unpin,
Collects at least limit_bytes from the body, preserving the rest.
Reads bytes from the stream until at least limit_bytes are buffered,
then returns both the buffered prefix and the remaining stream. This
enables inspecting a body prefix without consuming the entire stream.
§Examples
use hitbox_http::{BufferedBody, CollectExactResult};
async fn check_json_array<B: hyper::body::Body + Unpin>(
body: BufferedBody<B>,
) -> bool {
match body.collect_exact(1).await {
CollectExactResult::AtLeast { buffered, .. } => {
buffered.starts_with(b"[")
}
CollectExactResult::Incomplete { .. } => false,
}
}§Returns
AtLeast: Collected>= limit_bytes; remaining stream preservedIncomplete: Stream ended or error before reaching limit
§Errors
Stream errors are captured in CollectExactResult::Incomplete with the
error in the error field. Any bytes read before the error are preserved
in buffered.
§Performance
Only allocates for the prefix buffer (up to limit_bytes plus one frame).
The remaining stream is preserved without additional buffering.
§Use Cases
- Checking magic bytes for file type detection
- Reading fixed-size protocol headers
- Validating body format before full processing
- JQ/regex predicates that need body content
Trait Implementations§
Source§impl<B> Body for BufferedBody<B>where
B: HttpBody,
impl<B> Body for BufferedBody<B>where
B: HttpBody,
Source§fn poll_frame(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>>
fn poll_frame( self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>>
Source§fn size_hint(&self) -> SizeHint
fn size_hint(&self) -> SizeHint
Source§fn is_end_stream(&self) -> bool
fn is_end_stream(&self) -> bool
true when the end of stream has been reached. Read moreSource§impl<B> Debug for BufferedBody<B>where
B: HttpBody,
impl<B> Debug for BufferedBody<B>where
B: HttpBody,
impl<'pin, B> Unpin for BufferedBody<B>
Auto Trait Implementations§
impl<B> !Freeze for BufferedBody<B>
impl<B> RefUnwindSafe for BufferedBody<B>
impl<B> Send for BufferedBody<B>
impl<B> Sync for BufferedBody<B>
impl<B> UnwindSafe for BufferedBody<B>
Blanket Implementations§
Source§impl<T> BodyExt for T
impl<T> BodyExt for T
Source§fn frame(&mut self) -> Frame<'_, Self>where
Self: Unpin,
fn frame(&mut self) -> Frame<'_, Self>where
Self: Unpin,
Frame, if any.Source§fn map_frame<F, B>(self, f: F) -> MapFrame<Self, F>
fn map_frame<F, B>(self, f: F) -> MapFrame<Self, F>
Source§fn map_err<F, E>(self, f: F) -> MapErr<Self, F>
fn map_err<F, E>(self, f: F) -> MapErr<Self, F>
Source§fn boxed_unsync(self) -> UnsyncBoxBody<Self::Data, Self::Error>
fn boxed_unsync(self) -> UnsyncBoxBody<Self::Data, Self::Error>
Source§fn collect(self) -> Collect<Self>where
Self: Sized,
fn collect(self) -> Collect<Self>where
Self: Sized,
Collected body which will collect all the DATA frames
and trailers.Source§fn with_trailers<F>(self, trailers: F) -> WithTrailers<Self, F>
fn with_trailers<F>(self, trailers: F) -> WithTrailers<Self, F>
Source§fn into_data_stream(self) -> BodyDataStream<Self>where
Self: Sized,
fn into_data_stream(self) -> BodyDataStream<Self>where
Self: Sized,
BodyDataStream.