[][src]Trait hyperdrive::FromBody

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

Create an instance of this type from an HTTP request body, asynchronously.

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

Implementations of this function must not block, since this function is always run on a futures executor. If you need to perform blocking I/O or long-running computations, you can call tokio_threadpool::blocking.

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