hyperdriver/server/
builder.rs

1#[cfg(all(feature = "tls", feature = "stream"))]
2use std::sync::Arc;
3#[cfg(feature = "stream")]
4use std::{io, net::SocketAddr};
5
6use hyper::server::conn::{http1, http2};
7use tower::make::Shared;
8
9use crate::{bridge::rt::TokioExecutor, service::MakeServiceRef};
10
11use super::conn::auto;
12#[cfg(feature = "tls")]
13use super::conn::tls::info::TlsConnectionInfoService;
14#[cfg(feature = "stream")]
15use super::conn::Acceptor;
16use super::conn::MakeServiceConnectionInfoService;
17use super::Accept;
18use super::Server;
19
20/// Indicates that the Server requires an acceptor.
21#[derive(Debug, Clone, Copy, Default)]
22pub struct NeedsAcceptor {
23    _priv: (),
24}
25
26/// Indicates that the Server requires a protocol.
27#[derive(Debug, Clone, Copy, Default)]
28pub struct NeedsProtocol {
29    _priv: (),
30}
31
32/// Indicates that the Server requires a service.
33#[derive(Debug, Clone, Copy, Default)]
34pub struct NeedsService {
35    _priv: (),
36}
37
38/// Indicates that the Server requires an executor.
39#[derive(Debug, Clone, Copy, Default)]
40pub struct NeedsExecutor {
41    _priv: (),
42}
43
44impl<P, S, B, E> Server<NeedsAcceptor, P, S, B, E> {
45    /// Set the acceptor to use for incoming connections.
46    pub fn with_acceptor<A>(self, acceptor: A) -> Server<A, P, S, B, E>
47    where
48        A: Accept,
49    {
50        Server {
51            acceptor,
52            make_service: self.make_service,
53            protocol: self.protocol,
54            executor: self.executor,
55            body: self.body,
56        }
57    }
58
59    #[cfg(feature = "stream")]
60    /// Use an incoming stream of connections as the acceptor.
61    ///
62    /// This is a convenience method that constructs an `Acceptor` from the
63    /// provided stream of connections. It works with `tokio::net::TcpListener`,
64    /// `tokio::net::UnixListener`.
65    pub fn with_incoming<I>(self, incoming: I) -> Server<Acceptor, P, S, B, E>
66    where
67        I: Into<Acceptor> + Into<crate::server::conn::AcceptorCore>,
68    {
69        self.with_acceptor(Acceptor::from(incoming))
70    }
71
72    #[cfg(feature = "stream")]
73    /// Bind to the provided address and use it as the acceptor.
74    pub async fn with_bind(
75        self,
76        addr: &SocketAddr,
77    ) -> Result<Server<Acceptor, P, S, B, E>, io::Error> {
78        Ok(self.with_acceptor(Acceptor::bind(addr).await?))
79    }
80
81    #[cfg(feature = "stream")]
82    /// Use the provided listener as the acceptor.
83    pub async fn with_listener(
84        self,
85        listener: tokio::net::TcpListener,
86    ) -> Server<Acceptor, P, S, B, E> {
87        self.with_acceptor(Acceptor::from(listener))
88    }
89}
90
91impl<A, S, B, E> Server<A, NeedsProtocol, S, B, E> {
92    /// Set the protocol to use for incoming connections.
93    pub fn with_protocol<P>(self, protocol: P) -> Server<A, P, S, B, E> {
94        Server {
95            acceptor: self.acceptor,
96            make_service: self.make_service,
97            protocol,
98            executor: self.executor,
99            body: self.body,
100        }
101    }
102
103    /// Use a protocol that automatically detects and selects
104    /// between HTTP/1.1 and HTTP/2, by looking for the HTTP/2
105    /// header in the initial bytes of the connection.
106    pub fn with_auto_http(self) -> Server<A, auto::Builder, S, B, E> {
107        self.with_protocol(auto::Builder::default())
108    }
109
110    /// Use HTTP/1.1 for all incoming connections.
111    pub fn with_http1(self) -> Server<A, http1::Builder, S, B, E> {
112        self.with_protocol(http1::Builder::new())
113    }
114
115    /// Use HTTP/2 for all incoming connections.
116    pub fn with_http2(self) -> Server<A, http2::Builder<TokioExecutor>, S, B, E> {
117        self.with_protocol(http2::Builder::new(TokioExecutor::new()))
118    }
119}
120
121impl<A, P, B, E> Server<A, P, NeedsService, B, E> {
122    /// Set the make service to use for handling incoming connections.
123    ///
124    /// A `MakeService` is a factory for creating `Service` instances. It is
125    /// used to create a new `Service` for each incoming connection.
126    ///
127    /// If you have a service that is `Clone`, you can use `with_shared_service`
128    /// to wrap it in a `Shared` and avoid constructing a new make service.
129    pub fn with_make_service<S>(self, make_service: S) -> Server<A, P, S, B, E> {
130        Server {
131            acceptor: self.acceptor,
132            make_service,
133            protocol: self.protocol,
134            executor: self.executor,
135            body: self.body,
136        }
137    }
138
139    /// Wrap a `Clone` service in a `Shared` to use as a make service.
140    pub fn with_shared_service<S>(self, service: S) -> Server<A, P, Shared<S>, B, E> {
141        Server {
142            acceptor: self.acceptor,
143            make_service: Shared::new(service),
144            protocol: self.protocol,
145            executor: self.executor,
146            body: self.body,
147        }
148    }
149}
150
151impl<A, P, S, B, E> Server<A, P, S, B, E>
152where
153    S: MakeServiceRef<A::Conn, B>,
154    A: Accept,
155{
156    /// Wrap the make service in a service that provides connection information.
157    ///
158    /// This will make `crate::info::ConnectionInfo<A>` available in the request
159    /// extensions for each request handled by the generated service.
160    pub fn with_connection_info(self) -> Server<A, P, MakeServiceConnectionInfoService<S>, B, E> {
161        Server {
162            acceptor: self.acceptor,
163            make_service: MakeServiceConnectionInfoService::new(self.make_service),
164            protocol: self.protocol,
165            executor: self.executor,
166            body: self.body,
167        }
168    }
169
170    #[cfg(feature = "tls")]
171    /// Wrap the make service in a service that provides TLS connection information.
172    ///
173    /// This will make `crate::info::TlsConnectionInfo` available in the request
174    /// extensions for each request handled by the generated service.
175    pub fn with_tls_connection_info(self) -> Server<A, P, TlsConnectionInfoService<S>, B, E> {
176        Server {
177            acceptor: self.acceptor,
178            make_service: TlsConnectionInfoService::new(self.make_service),
179            protocol: self.protocol,
180            executor: self.executor,
181            body: self.body,
182        }
183    }
184}
185
186#[cfg(all(feature = "tls", feature = "stream"))]
187impl<P, S, B, E> Server<Acceptor, P, S, B, E> {
188    /// Use the provided `rustls::ServerConfig` to configure TLS
189    /// for incoming connections.
190    pub fn with_tls<C>(self, config: C) -> Server<Acceptor, P, S, B, E>
191    where
192        C: Into<Arc<rustls::ServerConfig>>,
193    {
194        Server {
195            acceptor: self.acceptor.with_tls(config.into()),
196            make_service: self.make_service,
197            protocol: self.protocol,
198            executor: self.executor,
199            body: self.body,
200        }
201    }
202}
203
204impl<A, P, S, B> Server<A, P, S, B, NeedsExecutor> {
205    /// Set the executor for this server
206    ///
207    /// The executor is used to drive connections to completion asynchronously.
208    pub fn with_executor<E>(self, executor: E) -> Server<A, P, S, B, E> {
209        Server {
210            acceptor: self.acceptor,
211            make_service: self.make_service,
212            protocol: self.protocol,
213            executor,
214            body: self.body,
215        }
216    }
217
218    /// Use a tokio multi-threaded excutor via [tokio::task::spawn]
219    ///
220    /// This executor is a suitable default, but does require Send and 'static
221    /// bounds in some places to allow futures to be moved between threads.
222    ///
223    /// Con
224    pub fn with_tokio(self) -> Server<A, P, S, B, TokioExecutor> {
225        self.with_executor(TokioExecutor::new())
226    }
227}
228
229impl<A, P, S, B, E> Server<A, P, S, B, E> {
230    /// Set the body to use for handling requests.
231    ///
232    /// Usually this method can be called with inferred
233    /// types.
234    pub fn with_body<B2>(self) -> Server<A, P, S, B2, E> {
235        Server {
236            acceptor: self.acceptor,
237            make_service: self.make_service,
238            protocol: self.protocol,
239            executor: self.executor,
240            body: Default::default(),
241        }
242    }
243}