Skip to main content

tako_rs_server/builder/
compio_server.rs

1use tako_rs_core::router::Router;
2
3use super::handle::ServerHandle;
4use super::spawn::make_handle;
5use super::spawn::spawn_done_compio;
6#[cfg(feature = "compio-tls")]
7use super::spawn::tls_alpn_for_tcp;
8#[cfg(feature = "compio-tls")]
9use super::tls_cert::TlsCert;
10#[cfg(feature = "compio-tls")]
11use super::tls_cert::build_rustls_server_config;
12use crate::ServerConfig;
13
14/// Fluent constructor for the compio-runtime [`CompioServer`].
15#[derive(Debug, Default, Clone)]
16pub struct CompioServerBuilder {
17  config: ServerConfig,
18  // Mirrors the gating on `CompioServer.tls` — only available when the
19  // `compio-tls` feature is on so non-TLS compio builds stay warning-clean.
20  #[cfg(feature = "compio-tls")]
21  tls: Option<TlsCert>,
22}
23
24impl CompioServerBuilder {
25  /// Override the [`ServerConfig`].
26  #[must_use]
27  pub fn config(mut self, config: ServerConfig) -> Self {
28    self.config = config;
29    self
30  }
31
32  /// Attach TLS material so [`CompioServer::spawn_tls`] becomes usable.
33  #[cfg(feature = "compio-tls")]
34  #[must_use]
35  pub fn tls(mut self, cert: TlsCert) -> Self {
36    self.tls = Some(cert);
37    self
38  }
39
40  /// Finalize and produce the [`CompioServer`].
41  pub fn build(self) -> CompioServer {
42    CompioServer {
43      config: self.config,
44      #[cfg(feature = "compio-tls")]
45      tls: self.tls,
46    }
47  }
48}
49
50/// Compio-runtime server entry point. Construct with [`CompioServer::builder`].
51///
52/// Mirrors the tokio `Server` API but drives the compio runtime —
53/// `io_uring` on Linux, IOCP on Windows, kqueue on macOS — under the hood.
54#[derive(Debug, Clone)]
55pub struct CompioServer {
56  config: ServerConfig,
57  // Only consumed by the `compio-tls` impl blocks below. Marking the field
58  // `cfg`-gated on the feature instead of `#[allow(dead_code)]` keeps the
59  // struct layout minimal in non-TLS compio builds.
60  #[cfg(feature = "compio-tls")]
61  tls: Option<TlsCert>,
62}
63
64impl CompioServer {
65  /// Start a fresh fluent builder.
66  #[must_use]
67  pub fn builder() -> CompioServerBuilder {
68    CompioServerBuilder::default()
69  }
70
71  /// Borrow the underlying [`ServerConfig`].
72  #[inline]
73  pub fn config(&self) -> &ServerConfig {
74    &self.config
75  }
76
77  /// Spawn a compio HTTP/1 server.
78  pub fn spawn_http(&self, listener: compio::net::TcpListener, router: Router) -> ServerHandle {
79    let (handle, shutdown_fut) = make_handle(self.config.drain_timeout);
80    let config = self.config.clone();
81    spawn_done_compio(handle.done.clone(), async move {
82      crate::server_compio::serve_with_shutdown_and_config(listener, router, shutdown_fut, config)
83        .await;
84    });
85    handle
86  }
87
88  /// Spawn a compio TLS server.
89  #[cfg(feature = "compio-tls")]
90  pub fn spawn_tls(&self, listener: compio::net::TcpListener, router: Router) -> ServerHandle {
91    let tls = self
92      .tls
93      .clone()
94      .expect("CompioServer::spawn_tls requires a TlsCert (use builder().tls(...))");
95    let (handle, shutdown_fut) = make_handle(self.config.drain_timeout);
96    let config = self.config.clone();
97    let alpn = tls_alpn_for_tcp();
98    spawn_done_compio(handle.done.clone(), async move {
99      if let TlsCert::PemPaths {
100        cert_path,
101        key_path,
102        client_auth: None,
103      } = &tls
104      {
105        crate::server_tls_compio::serve_tls_with_shutdown_and_config(
106          listener,
107          router,
108          Some(cert_path.as_str()),
109          Some(key_path.as_str()),
110          shutdown_fut,
111          config,
112        )
113        .await;
114        return;
115      }
116      let rustls_cfg = match build_rustls_server_config(&tls, alpn) {
117        Ok(c) => c,
118        Err(e) => {
119          tracing::error!("CompioServer::spawn_tls: failed to build rustls config: {e}");
120          return;
121        }
122      };
123      crate::server_tls_compio::serve_tls_with_rustls_config_and_shutdown(
124        listener,
125        router,
126        rustls_cfg,
127        shutdown_fut,
128        config,
129      )
130      .await;
131    });
132    handle
133  }
134}