hyper_serve/
service.rs

1//! Service traits.
2
3use http::Response;
4use http_body::Body;
5use pin_project_lite::pin_project;
6use std::{
7    future::Future,
8    pin::Pin,
9    task::{Context, Poll},
10};
11use tower::{util::Oneshot, ServiceExt};
12use tower_service::Service;
13
14/// Trait alias for [`Service`] with bounds required for [`serve`](crate::server::Server::serve).
15///
16/// This trait is sealed and cannot be implemented for types outside this crate.
17#[allow(missing_docs)]
18pub trait SendService<Request>: send_service::Sealed<Request> {
19    type Service: Service<
20            Request,
21            Response = Response<Self::Body>,
22            Error = Self::Error,
23            Future = Self::Future,
24        > + Send
25        + Clone
26        + 'static;
27
28    type Body: Body<Data = Self::BodyData, Error = Self::BodyError> + Send + 'static;
29    type BodyData: Send + 'static;
30    type BodyError: Into<Box<dyn std::error::Error + Send + Sync>>;
31
32    type Error: Into<Box<dyn std::error::Error + Send + Sync>>;
33
34    type Future: Future<Output = Result<Response<Self::Body>, Self::Error>> + Send + 'static;
35
36    fn into_service(self) -> Self::Service;
37}
38
39impl<T, B, Request> send_service::Sealed<Request> for T
40where
41    T: Service<Request, Response = Response<B>>,
42    T::Error: Into<Box<dyn std::error::Error + Send + Sync>>,
43    T::Future: Send + 'static,
44    B: Body + Send + 'static,
45    B::Data: Send + 'static,
46    B::Error: Into<Box<dyn std::error::Error + Send + Sync>>,
47{
48}
49
50impl<T, B, Request> SendService<Request> for T
51where
52    T: Service<Request, Response = Response<B>> + Send + Clone + 'static,
53    T::Error: Into<Box<dyn std::error::Error + Send + Sync>>,
54    T::Future: Send + 'static,
55    B: Body + Send + 'static,
56    B::Data: Send + 'static,
57    B::Error: Into<Box<dyn std::error::Error + Send + Sync>>,
58{
59    type Service = T;
60
61    type Body = B;
62    type BodyData = B::Data;
63    type BodyError = B::Error;
64
65    type Error = T::Error;
66
67    type Future = T::Future;
68
69    fn into_service(self) -> Self::Service {
70        self
71    }
72}
73
74/// Modified version of [`MakeService`] that takes a `&Target` and has required trait bounds for
75/// [`serve`](crate::server::Server::serve).
76///
77/// This trait is sealed and cannot be implemented for types outside this crate.
78///
79/// [`MakeService`]: https://docs.rs/tower/0.4/tower/make/trait.MakeService.html
80#[allow(missing_docs)]
81pub trait MakeService<Target, Request>: make_service_ref::Sealed<(Target, Request)> {
82    type Service: Service<
83            Request,
84            Response = Response<Self::Body>,
85            Error = Self::Error,
86            Future = Self::Future,
87        >
88        + Send
89        + 'static
90        + Clone;
91
92    type Body: Body<Data = Self::BodyData, Error = Self::BodyError> + Send + 'static;
93    type BodyData: Send + 'static;
94    type BodyError: Into<Box<dyn std::error::Error + Send + Sync>>;
95
96    type Error: Into<Box<dyn std::error::Error + Send + Sync>>;
97
98    type Future: Future<Output = Result<Response<Self::Body>, Self::Error>> + Send + 'static;
99
100    type MakeError: Into<Box<dyn std::error::Error + Send + Sync>>;
101    type MakeFuture: Future<Output = Result<Self::Service, Self::MakeError>>;
102
103    fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::MakeError>>;
104
105    fn make_service(&mut self, target: Target) -> Self::MakeFuture;
106}
107
108impl<T, S, B, E, F, Target, Request> make_service_ref::Sealed<(Target, Request)> for T
109where
110    T: Service<Target, Response = S, Error = E, Future = F>,
111    S: Service<Request, Response = Response<B>> + Send + 'static,
112    S::Error: Into<Box<dyn std::error::Error + Send + Sync>>,
113    S::Future: Send + 'static,
114    B: Body + Send + 'static,
115    B::Data: Send + 'static,
116    B::Error: Into<Box<dyn std::error::Error + Send + Sync>>,
117    E: Into<Box<dyn std::error::Error + Send + Sync>>,
118    F: Future<Output = Result<S, E>>,
119{
120}
121
122impl<T, S, B, E, F, Target, Request> MakeService<Target, Request> for T
123where
124    T: Service<Target, Response = S, Error = E, Future = F>,
125    S: Service<Request, Response = Response<B>> + Send + Clone + 'static,
126    S::Error: Into<Box<dyn std::error::Error + Send + Sync>>,
127    S::Future: Send + 'static,
128    B: Body + Send + 'static,
129    B::Data: Send + 'static,
130    B::Error: Into<Box<dyn std::error::Error + Send + Sync>>,
131    E: Into<Box<dyn std::error::Error + Send + Sync>>,
132    F: Future<Output = Result<S, E>>,
133{
134    type Service = S;
135
136    type Body = B;
137    type BodyData = B::Data;
138    type BodyError = B::Error;
139
140    type Error = S::Error;
141
142    type Future = S::Future;
143
144    type MakeError = E;
145    type MakeFuture = F;
146
147    fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::MakeError>> {
148        self.poll_ready(cx)
149    }
150
151    fn make_service(&mut self, target: Target) -> Self::MakeFuture {
152        self.call(target)
153    }
154}
155
156mod send_service {
157    pub trait Sealed<T> {}
158}
159
160mod make_service_ref {
161    pub trait Sealed<T> {}
162}
163
164/// A tower service converted into a hyper service.
165#[derive(Debug, Copy, Clone)]
166pub(crate) struct TowerToHyperService<S> {
167    service: S,
168}
169
170impl<S> TowerToHyperService<S> {
171    /// Create a new `TowerToHyperService` from a tower service.
172    pub(crate) fn new(tower_service: S) -> Self {
173        Self {
174            service: tower_service,
175        }
176    }
177}
178
179impl<S, R> hyper::service::Service<R> for TowerToHyperService<S>
180where
181    S: tower_service::Service<R> + Clone,
182{
183    type Response = S::Response;
184    type Error = S::Error;
185    type Future = TowerToHyperServiceFuture<S, R>;
186
187    fn call(&self, req: R) -> Self::Future {
188        TowerToHyperServiceFuture {
189            future: self.service.clone().oneshot(req),
190        }
191    }
192}
193
194pin_project! {
195    /// Response future for [`TowerToHyperService`].
196    pub struct TowerToHyperServiceFuture<S, R>
197    where
198        S: tower_service::Service<R>,
199    {
200        #[pin]
201        future: Oneshot<S, R>,
202    }
203}
204
205impl<S, R> Future for TowerToHyperServiceFuture<S, R>
206where
207    S: tower_service::Service<R>,
208{
209    type Output = Result<S::Response, S::Error>;
210
211    #[inline]
212    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
213        self.project().future.poll(cx)
214    }
215}