1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
use std::sync::Arc;

use futures::Future;
use http;

use {Body, BodyStream, BoxedResponse, Error, Responder, ResponseBuilder};

/// A trait indicating that the type can be used to handler to a HTTP request.
///
/// The `Handler` trait is most commonly used through functions of the following type, for which it
/// is automatically implemented:
///
/// ```ignore
/// Fn(http::Request<impl Body>, http::response::Builder) -> impl Responder
/// ```
///
/// It can also be implemented manually for more complex types, which store state associated with
/// the handler.
///
/// # Example
///
/// A function which implements the `Handler` trait:
///
/// ```
/// # extern crate aitch;
/// # extern crate http;
/// #
/// # use aitch::{Responder, ResponseBuilder};
/// # use http::Request;
/// #
/// fn handler(_: http::Request<()>, mut resp: ResponseBuilder) -> impl Responder {
///     resp.body("Hello, world".to_owned())
/// }
/// ```
///
/// A more complex type can also implement the `Handler` trait directly:
///
/// ```
/// # extern crate aitch;
/// # extern crate http;
/// #
/// # use aitch::{Handler, Responder, ResponseBuilder};
/// # use http::Request;
/// #
/// struct ComplexHandler {
///     message: String
/// }
///
/// impl Handler<()> for ComplexHandler {
///     type Resp = http::Result<http::Response<String>>;
///
///     fn handle(&self, _: Request<()>, mut resp: ResponseBuilder) -> Self::Resp {
///         resp.body(self.message.clone())
///     }
/// }
/// ```
///
/// # Storing a `Handler`
///
/// If you need to store a `Handler`, the [`BoxedHandler`] type (and corresponding [`box_handler`]
/// function) can be used to erase the generic types of the handler.
///
/// This can be particularly useful if you need to store multiple handlers (such as in a request
/// router) which may deal with different request/response bodies, or use different [`Responder`]
/// types.
///
/// [`BoxedHandler`]: type.BoxedHandler.html
/// [`box_handler`]: fn.box_handler.html
/// [`Responder`]: trait.Responder.html
pub trait Handler<ReqBody>
where
    ReqBody: Body,
    Self: Send + Sync + 'static,
{
    /// The `Responder` type returned by this `Handler`.
    type Resp: Responder;

    /// Handles an incoming HTTP request, returning a `Responder` describing a HTTP response.
    fn handle(&self, http::Request<ReqBody>, ResponseBuilder) -> Self::Resp;
}

impl<Func, ReqBody, Resp> Handler<ReqBody> for Func
where
    Func: Fn(http::Request<ReqBody>, ResponseBuilder) -> Resp + Send + Sync + 'static,
    ReqBody: Body,
    Resp: Responder,
{
    type Resp = Resp;

    fn handle(&self, req: http::Request<ReqBody>, resp: ResponseBuilder) -> Resp {
        (self)(req, resp)
    }
}

/// A `Box<Handler>` with all types erased.
///
/// This allows multiple handlers with different type signature (e.g. different body/responder
/// types) to be stored in the same data-structure.
///
/// # Example
///
/// ```
/// # extern crate aitch;
/// # extern crate http;
/// #
/// # use std::collections::HashMap;
/// #
/// # use aitch::{
/// #     BodyStream, BoxedHandler, BoxedResponse, Handler, Responder, ResponseBuilder
/// # };
/// # use http::Request;
/// #
/// /// A Very Simple Router which matches handlers based on the full path in request URIs.
/// struct VerySimpleRouter(pub HashMap<String, BoxedHandler>);
///
/// impl Handler<BodyStream> for VerySimpleRouter {
///     type Resp = BoxedResponse;
///
///     fn handle(&self, req: Request<BodyStream>, mut resp: ResponseBuilder) -> BoxedResponse {
///         match self.0.get(req.uri().path()) {
///             Some(handler) => handler.handle(req, resp),
///             // Note the use of `.into_response()`, which boxes the response to erase any
///             // type variables used by the responder, matching the response type used by
///             // `BoxedHandler` above.
///             None => resp.status(http::StatusCode::NOT_FOUND).body(()).into_response(),
///         }
///     }
/// }
/// ```
///
/// See the [`SimpleRouter` source code] for a (slightly) more complete example.
///
/// [`SimpleRouter` source code]: ../src/aitch/middlewares/router.rs.html
pub type BoxedHandler = Box<Handler<BodyStream, Resp = BoxedResponse>>;

fn map_request_body<B1, B2>(
    req: http::Request<B1>,
) -> impl Future<Item = http::Request<B2>, Error = Error>
where
    B1: Body,
    B2: Body,
{
    let (parts, body) = req.into_parts();
    body.into_body::<B2>()
        .map(move |body| http::Request::from_parts(parts, body))
}

/// Creates a [`BoxedHandler`] from any [`Handler`].
///
/// See the [`BoxedHandler`] for more details about how this can be used.
///
/// [`BoxedHandler`]: type.BoxedHandler.html
/// [`Handler`]: trait.Handler.html
pub fn box_handler<B: Body>(handler: impl Handler<B>) -> BoxedHandler {
    let handler = Arc::new(handler);
    let closure = move |req, resp| -> BoxedResponse {
        let handler = handler.clone();
        let resp =
            map_request_body(req).and_then(move |req| handler.handle(req, resp).into_response());
        Box::new(resp)
    };
    Box::new(closure)
}