Skip to main content

BufferedBody

Enum BufferedBody 

Source
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 memory
  • Partial: Prefix buffered, remaining stream preserved
  • Passthrough: 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()──────────► Complete

Variants§

§

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.

Source

pub async fn collect(self) -> Result<Bytes, Self>
where B::Data: Send,

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_exact to 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.

Source

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 preserved
  • Incomplete: 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,

Source§

type Data = Bytes

Values yielded by the Body.
Source§

type Error = <B as Body>::Error

The error type this Body might generate.
Source§

fn poll_frame( self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>>

Attempt to pull out the next data buffer of this stream.
Source§

fn size_hint(&self) -> SizeHint

Returns the bounds on the remaining length of the stream. Read more
Source§

fn is_end_stream(&self) -> bool

Returns true when the end of stream has been reached. Read more
Source§

impl<B> Debug for BufferedBody<B>
where B: HttpBody,

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'pin, B> Unpin for BufferedBody<B>
where B: HttpBody, PinnedFieldsOf<__BufferedBody<'pin, B>>: Unpin,

Auto Trait Implementations§

§

impl<B> !Freeze for BufferedBody<B>

§

impl<B> RefUnwindSafe for BufferedBody<B>

§

impl<B> Send for BufferedBody<B>
where B: Send, <B as Body>::Error: Send,

§

impl<B> Sync for BufferedBody<B>
where B: Sync, <B as Body>::Error: Sync,

§

impl<B> UnwindSafe for BufferedBody<B>
where B: UnwindSafe, <B as Body>::Error: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> BodyExt for T
where T: Body + ?Sized,

Source§

fn frame(&mut self) -> Frame<'_, Self>
where Self: Unpin,

Returns a future that resolves to the next Frame, if any.
Source§

fn map_frame<F, B>(self, f: F) -> MapFrame<Self, F>
where Self: Sized, F: FnMut(Frame<Self::Data>) -> Frame<B>, B: Buf,

Maps this body’s frame to a different kind.
Source§

fn map_err<F, E>(self, f: F) -> MapErr<Self, F>
where Self: Sized, F: FnMut(Self::Error) -> E,

Maps this body’s error value to a different value.
Source§

fn boxed(self) -> BoxBody<Self::Data, Self::Error>
where Self: Sized + Send + Sync + 'static,

Turn this body into a boxed trait object.
Source§

fn boxed_unsync(self) -> UnsyncBoxBody<Self::Data, Self::Error>
where Self: Sized + Send + 'static,

Turn this body into a boxed trait object that is !Sync.
Source§

fn collect(self) -> Collect<Self>
where Self: Sized,

Turn this body into Collected body which will collect all the DATA frames and trailers.
Source§

fn with_trailers<F>(self, trailers: F) -> WithTrailers<Self, F>
where Self: Sized, F: Future<Output = Option<Result<HeaderMap, Self::Error>>>,

Add trailers to the body. Read more
Source§

fn into_data_stream(self) -> BodyDataStream<Self>
where Self: Sized,

Turn this body into BodyDataStream.
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more