[][src]Trait hyperdrive::FromBody

pub trait FromBody: Sized {
    type Context: RequestContext;
    type Result: IntoFuture<Item = Self, Error = BoxedError>;
    fn from_body(
        request: &Request<()>,
        body: Body,
        context: &Self::Context
    ) -> Self::Result; }

Asynchronous conversion from an HTTP request body.

Types implementing this trait are provided in the body module. They allow easy deserialization from a variety of data formats.

Examples

Collect the whole body and then deserialize it using a serde data format crate serde_whatever:

struct CustomFormat<T>(T);

impl<T: serde::de::DeserializeOwned + Send + 'static> FromBody for CustomFormat<T> {
    type Context = NoContext;
    type Result = DefaultFuture<Self, BoxedError>;

    fn from_body(
        request: &http::Request<()>,
        body: hyper::Body,
        context: &Self::Context,
    ) -> Self::Result {
        Box::new(body.concat2().map_err(Into::into).and_then(|body| {
            match serde_whatever::from_slice(&body) {
                Ok(t) => Ok(CustomFormat(t)),
                Err(e) => Err(e.into()),
            }
        }))
    }
}

Process the body stream on-the-fly and calculate a checksum by adding all the bytes:

struct BodyChecksum(u8);

impl FromBody for BodyChecksum {
    type Context = NoContext;
    type Result = DefaultFuture<Self, BoxedError>;

    fn from_body(
        request: &http::Request<()>,
        body: hyper::Body,
        context: &Self::Context,
    ) -> Self::Result {
        Box::new(body
            .map_err(BoxedError::from)
            .fold(0, |checksum, chunk| -> Result<_, BoxedError> {
                Ok(chunk.as_ref().iter()
                    .fold(checksum, |checksum: u8, byte| {
                        checksum.wrapping_add(*byte)
                }))
            })
            .map(|checksum| BodyChecksum(checksum))  // wrap it up to create a `Self`
        )
    }
}

Associated Types

type Context: RequestContext

A context parameter passed to from_body.

This can be used to pass application-specific data like a logger or a database connection around.

If no context is needed, this should be set to NoContext.

type Result: IntoFuture<Item = Self, Error = BoxedError>

The result returned by from_body.

Because impl Trait cannot be used inside traits (and named existential types aren't stable), the type here might not be nameable. In that case, you can set it to DefaultFuture<Self, Error> and box the returned future.

If your FromBody implementation doesn't need to return a future, you can set this to Result<Self, BoxedError> and immediately return the result of the conversion.

Loading content...

Required methods

fn from_body(
    request: &Request<()>,
    body: Body,
    context: &Self::Context
) -> Self::Result

Create a Self from an HTTP request body.

This will consume the body, so only one FromBody type can be used for every processed request.

Note: You probably want to limit the size of the body to prevent denial of service attacks.

Parameters

  • request: An HTTP request (without body) from the http crate.
  • body: The body stream. Implements futures::Stream.
  • context: User-defined context.
Loading content...

Implementors

impl<T: DeserializeOwned + Send + 'static> FromBody for HtmlForm<T>[src]

type Context = NoContext

type Result = DefaultFuture<Self, BoxedError>

impl<T: DeserializeOwned + Send + 'static> FromBody for Json<T>[src]

type Context = NoContext

type Result = DefaultFuture<Self, BoxedError>

Loading content...