tower_server/
tls.rs

1//! TLS support.
2
3use std::sync::Arc;
4
5use futures_util::{stream::BoxStream, StreamExt};
6use http::Request;
7use hyper::body::Incoming;
8use rustls::{ServerConfig, ServerConnection};
9
10/// A TLS configurer that may change during lifetime of a server.
11///
12/// The configurer supports "hotpatching" a running server with new configuration.
13pub trait TlsConfigurer {
14    /// Whether the configuration may change over time.
15    fn is_dynamic(&self) -> bool;
16
17    /// Turn the configurer into a stream of TLS [ServerConfig]s.
18    fn into_stream(self) -> BoxStream<'static, Arc<ServerConfig>>;
19}
20
21impl TlsConfigurer for () {
22    fn is_dynamic(&self) -> bool {
23        false
24    }
25
26    fn into_stream(self) -> BoxStream<'static, Arc<ServerConfig>> {
27        futures_util::stream::empty().boxed()
28    }
29}
30
31impl TlsConfigurer for rustls::server::ServerConfig {
32    fn is_dynamic(&self) -> bool {
33        false
34    }
35
36    fn into_stream(self) -> BoxStream<'static, Arc<ServerConfig>> {
37        futures_util::stream::iter([Arc::new(self)]).boxed()
38    }
39}
40
41impl TlsConfigurer for Arc<rustls::server::ServerConfig> {
42    fn is_dynamic(&self) -> bool {
43        false
44    }
45
46    fn into_stream(self) -> BoxStream<'static, Arc<ServerConfig>> {
47        futures_util::stream::iter([self]).boxed()
48    }
49}
50
51impl TlsConfigurer for Arc<dyn Fn() -> Arc<rustls::server::ServerConfig> + Send + Sync> {
52    fn is_dynamic(&self) -> bool {
53        false
54    }
55
56    fn into_stream(self) -> BoxStream<'static, Arc<ServerConfig>> {
57        futures_util::stream::once(async move { (self)() }).boxed()
58    }
59}
60
61impl TlsConfigurer for BoxStream<'static, Arc<ServerConfig>> {
62    fn is_dynamic(&self) -> bool {
63        true
64    }
65
66    fn into_stream(self) -> BoxStream<'static, Arc<ServerConfig>> {
67        self
68    }
69}
70
71/// A middleware for Tls connections.
72///
73/// This middleware is implemented in two steps, first a data extraction step taking a [ServerConnection],
74/// then a HTTP request middleware runs with that data as a parameter.
75pub trait TlsConnectionMiddleware: Clone + Send + 'static {
76    /// The data extracted from the rustls ServerConnection.
77    type Data: Send;
78
79    /// Extract data from a [ServerConnection].
80    fn data(&self, connection: &ServerConnection) -> Self::Data;
81
82    /// Call middleware with extracted data.
83    fn call(&self, req: &mut Request<Incoming>, data: &Self::Data);
84}
85
86/// A TLS connection middleware that does nothing.
87#[derive(Clone, Copy)]
88pub struct NoOpTlsConnectionMiddleware;
89
90impl TlsConnectionMiddleware for NoOpTlsConnectionMiddleware {
91    type Data = ();
92
93    fn data(&self, _connection: &ServerConnection) -> Self::Data {}
94
95    fn call(&self, _req: &mut Request<Incoming>, _data: &Self::Data) {}
96}