Skip to main content

alux_http_hyper/
route.rs

1//! The compiled surface, as a route hyper can serve.
2
3use crate::message::{BODY_LIMIT, HyperAnswer, answered, asked};
4use alux_http_direct::DirectRoute;
5use bytes::Bytes;
6use core::convert::Infallible;
7use core::fmt::Display;
8use core::future::Future;
9use core::pin::Pin;
10use derive_new::new as New;
11use hyper::Request;
12use hyper::body::Body;
13use hyper::service::Service;
14
15/// Serves one compiled surface over hyper.
16///
17/// The surface does the routing and the reading; this states only how a hyper request becomes one a
18/// surface answers, and how that answer becomes a hyper response.
19#[derive(Clone, New)]
20pub struct HyperRoute {
21    surface: DirectRoute,
22    #[new(value = "BODY_LIMIT")]
23    reading: usize,
24}
25
26impl HyperRoute {
27    /// Reads a request body of at most `bytes`, answering `413` for one larger than that.
28    ///
29    /// What a service accepts is the service's to state. The default is a sane bound rather than a
30    /// policy, so anything serving callers it does not control states its own.
31    #[must_use]
32    pub const fn reading(mut self, bytes: usize) -> Self {
33        self.reading = bytes;
34
35        self
36    }
37
38    /// Answers one request, whatever carried it here.
39    ///
40    /// A request that cannot be read is answered rather than dropped, because a caller that sent
41    /// something unreadable is still owed an answer.
42    pub async fn answer<Sent>(&self, request: Request<Sent>) -> HyperAnswer
43    where
44        Sent: Body<Data = Bytes>,
45        Sent::Error: Display,
46    {
47        match asked(request, self.reading).await {
48            Ok(asked) => answered(self.surface.answer(asked).await),
49            Err(answer) => answered(answer),
50        }
51    }
52}
53
54impl<Sent> Service<Request<Sent>> for HyperRoute
55where
56    Sent: Body<Data = Bytes> + Send + 'static,
57    Sent::Error: Display,
58{
59    type Response = HyperAnswer;
60    type Error = Infallible;
61    type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send>>;
62
63    fn call(&self, request: Request<Sent>) -> Self::Future {
64        let served = self.clone();
65
66        Box::pin(async move { Ok(served.answer(request).await) })
67    }
68}