SharedBody

Struct SharedBody 

Source
pub struct SharedBody<B>
where B: Body + Unpin, B::Data: Clone, B::Error: Clone,
{ /* private fields */ }
Expand description

A cloneable HTTP body wrapper that allows multiple consumers to share the same body.

SharedBody wraps any http_body::Body that is Unpin and whose data and error types implement Clone, allowing it to be cloned and consumed by multiple tasks simultaneously. All clones share the same underlying body state and position.

§Examples

Basic usage with concurrent consumers:

use shared_http_body::SharedBody;
use http_body_util::{BodyExt, StreamBody};
use http_body::Frame;
use bytes::Bytes;
use futures_util::stream;

let chunks = vec!["hello", "world"];
let stream = stream::iter(chunks.into_iter().map(|s| Ok::<_, std::convert::Infallible>(Frame::data(Bytes::from(s)))));
let body = StreamBody::new(stream);
let shared_body = SharedBody::new(body);

// Create multiple consumers
let consumer1 = shared_body.clone();
let consumer2 = shared_body.clone();

// Both will receive all frames
let result1 = consumer1.collect().await.unwrap().to_bytes();
let result2 = consumer2.collect().await.unwrap().to_bytes();

assert_eq!(result1, Bytes::from("helloworld"));
assert_eq!(result2, Bytes::from("helloworld"));

Cloning after partial consumption:

use shared_http_body::SharedBody;
use http_body_util::{BodyExt, StreamBody};
use http_body::Frame;
use bytes::Bytes;
use futures_util::stream;

let chunks = vec!["first", "second", "third"];
let stream = stream::iter(chunks.into_iter().map(|s| Ok::<_, std::convert::Infallible>(Frame::data(Bytes::from(s)))));
let body = StreamBody::new(stream);
let mut shared_body = SharedBody::new(body);

// Consume first frame
use http_body_util::BodyExt;
let _ = http_body_util::BodyExt::frame(&mut shared_body).await;

// Clone after partial consumption
let cloned = shared_body.clone();
let remaining = cloned.collect().await.unwrap().to_bytes();

// Clone only sees remaining frames
assert_eq!(remaining, Bytes::from("secondthird"));

§Requirements

The wrapped body must satisfy these bounds:

  • http_body::Body: The type must implement the Body trait
  • Unpin: Required for safe polling without pinning
  • Clone for Body::Data: The data type must be cloneable
  • Clone for Body::Error: The error type must be cloneable

§Thread Safety

SharedBody is both Send and Sync when the underlying body and its data/error types are Send and Sync. This means cloned bodies can be safely moved across threads and shared between tasks running on different threads.

Implementations§

Source§

impl<B> SharedBody<B>
where B: Body + Unpin, B::Data: Clone, B::Error: Clone,

Source

pub fn new(body: B) -> Self

Creates a new SharedBody from the given HTTP body.

The body must implement Unpin, and both its data type (Body::Data) and error type (Body::Error) must implement Clone. Once created, the SharedBody can be cloned to create multiple consumers that all share the same underlying body state.

§Examples
use shared_http_body::SharedBody;
use http_body_util::StreamBody;
use http_body::Frame;
use bytes::Bytes;
use futures_util::stream;

let chunks = vec!["hello", "world"];
let stream = stream::iter(chunks.into_iter().map(|s| Ok::<_, std::convert::Infallible>(Frame::data(Bytes::from(s)))));
let body = StreamBody::new(stream);
let shared_body = SharedBody::new(body);
§Panics

This method does not panic under normal circumstances.

Trait Implementations§

Source§

impl<B> Body for SharedBody<B>
where B: Body + Unpin, B::Data: Clone, B::Error: Clone,

Source§

type Data = <B as Body>::Data

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 is_end_stream(&self) -> bool

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

fn size_hint(&self) -> SizeHint

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

impl<B> Clone for SharedBody<B>
where B: Body + Unpin, B::Data: Clone, B::Error: Clone,

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<B> Debug for SharedBody<B>
where B: Body + Unpin + Debug, B::Data: Clone, B::Error: Clone,

Source§

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

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<B> Freeze for SharedBody<B>
where <B as Body>::Error: Sized, <B as Body>::Data: Sized,

§

impl<B> !RefUnwindSafe for SharedBody<B>

§

impl<B> Send for SharedBody<B>
where <B as Body>::Error: Sized + Send + Sync, <B as Body>::Data: Sized + Send + Sync, B: Send,

§

impl<B> Sync for SharedBody<B>
where <B as Body>::Error: Sized + Send + Sync, <B as Body>::Data: Sized + Send + Sync, B: Send,

§

impl<B> Unpin for SharedBody<B>
where <B as Body>::Error: Sized, <B as Body>::Data: Sized,

§

impl<B> !UnwindSafe for SharedBody<B>

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> 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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

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<B> SharedBodyExt for B
where B: Body,

Source§

fn into_shared(self) -> SharedBody<Self>
where Self: Sized + Unpin, Self::Data: Clone, Self::Error: Clone,

Converts this HTTP body into a SharedBody. Read more
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
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.