Skip to main content

trillium_http/
server_config.rs

1use crate::{Conn, ConnectionStatus, HttpConfig, Result, TypeSet, Upgrade};
2use fieldwork::Fieldwork;
3use futures_lite::{AsyncRead, AsyncWrite};
4use std::{future::Future, sync::Arc};
5use swansong::{ShutdownCompletion, Swansong};
6/// This struct represents the shared configuration and context for a http server.
7///
8/// This currently contains tunable parameters in a [`HttpConfig`], the [`Swansong`] graceful
9/// shutdown control interface, and a shared [`TypeSet`] that contains application-specific
10/// information about the running server
11#[derive(Default, Debug, Fieldwork)]
12#[fieldwork(get, set, get_mut, with)]
13pub struct ServerConfig {
14    /// [`HttpConfig`] performance and security parameters
15    pub(crate) http_config: HttpConfig,
16
17    /// [`Swansong`] graceful shutdown interface
18    pub(crate) swansong: Swansong,
19
20    /// [`TypeSet`] shared state
21    pub(crate) shared_state: TypeSet,
22}
23impl AsRef<TypeSet> for ServerConfig {
24    fn as_ref(&self) -> &TypeSet {
25        &self.shared_state
26    }
27}
28
29impl AsMut<TypeSet> for ServerConfig {
30    fn as_mut(&mut self) -> &mut TypeSet {
31        &mut self.shared_state
32    }
33}
34
35impl AsRef<Swansong> for ServerConfig {
36    fn as_ref(&self) -> &Swansong {
37        &self.swansong
38    }
39}
40
41impl AsRef<HttpConfig> for ServerConfig {
42    fn as_ref(&self) -> &HttpConfig {
43        &self.http_config
44    }
45}
46
47impl ServerConfig {
48    /// Construct a new `ServerConfig`
49    pub fn new() -> Self {
50        Self::default()
51    }
52
53    /// Perform HTTP on the provided transport, applying the provided `async Conn -> Conn` handler
54    /// function for every distinct http request-response.
55    ///
56    /// For any given invocation of `ServerConfig::run`, the handler function may run any number of
57    /// times, depending on whether the connection is reused by the client.
58    ///
59    /// This can only be called on an `Arc<ServerConfig>` because an arc clone is moved into the
60    /// Conn.
61    ///
62    /// # Errors
63    ///
64    /// This function will return an [`Error`](crate::Error) if any of the http requests is
65    /// irrecoverably malformed or otherwise noncompliant.
66    pub async fn run<Transport, Handler, Fut>(
67        self: Arc<Self>,
68        transport: Transport,
69        mut handler: Handler,
70    ) -> Result<Option<Upgrade<Transport>>>
71    where
72        Transport: AsyncRead + AsyncWrite + Unpin + Send + Sync + 'static,
73        Handler: FnMut(Conn<Transport>) -> Fut,
74        Fut: Future<Output = Conn<Transport>>,
75    {
76        let _guard = self.swansong.guard();
77        let buffer = Vec::with_capacity(self.http_config.request_buffer_initial_len).into();
78
79        let mut conn = Conn::new_internal(self, transport, buffer).await?;
80
81        loop {
82            conn = match handler(conn).await.send().await? {
83                ConnectionStatus::Upgrade(upgrade) => return Ok(Some(upgrade)),
84                ConnectionStatus::Close => return Ok(None),
85                ConnectionStatus::Conn(next) => next,
86            }
87        }
88    }
89
90    /// Attempt graceful shutdown of this server.
91    ///
92    /// The returned [`ShutdownCompletion`] type can
93    /// either be awaited in an async context or blocked on with [`ShutdownCompletion::block`] in a
94    /// blocking context
95    pub fn shut_down(&self) -> ShutdownCompletion {
96        self.swansong.shut_down()
97    }
98}