1use std::fmt::Debug;
2use std::net::SocketAddr;
3
4use crate::error::HttpError;
5use crate::service::{HttpService, HttpServiceFactory};
6
7#[derive(Debug, Clone, bon::Builder)]
13#[builder(state_mod(vis = "pub(crate)"))]
14#[allow(dead_code)]
15pub struct HttpServer<F> {
16 #[builder(default = scuffle_context::Context::global())]
18 ctx: scuffle_context::Context,
19 #[builder(default = 1)]
21 worker_tasks: usize,
22 service_factory: F,
24 bind: SocketAddr,
29 #[builder(default = true)]
31 #[cfg(feature = "http1")]
32 #[cfg_attr(docsrs, doc(cfg(feature = "http1")))]
33 enable_http1: bool,
34 #[builder(default = true)]
36 #[cfg(feature = "http2")]
37 #[cfg_attr(docsrs, doc(cfg(feature = "http2")))]
38 enable_http2: bool,
39 #[builder(default = false, setters(vis = "", name = enable_http3_internal))]
40 #[cfg(feature = "http3")]
41 #[cfg_attr(docsrs, doc(cfg(feature = "http3")))]
42 enable_http3: bool,
43 #[cfg(feature = "tls-rustls")]
48 #[cfg_attr(docsrs, doc(cfg(feature = "tls-rustls")))]
49 rustls_config: Option<rustls::ServerConfig>,
50}
51
52#[cfg(feature = "http3")]
53#[cfg_attr(docsrs, doc(cfg(feature = "http3")))]
54impl<F, S> HttpServerBuilder<F, S>
55where
56 S: http_server_builder::State,
57 S::EnableHttp3: http_server_builder::IsUnset,
58 S::RustlsConfig: http_server_builder::IsSet,
59{
60 pub fn enable_http3(self, enable_http3: bool) -> HttpServerBuilder<F, http_server_builder::SetEnableHttp3<S>> {
64 self.enable_http3_internal(enable_http3)
65 }
66}
67
68#[cfg(feature = "tower")]
69#[cfg_attr(docsrs, doc(cfg(feature = "tower")))]
70impl<M, S> HttpServerBuilder<crate::service::TowerMakeServiceFactory<M, ()>, S>
71where
72 M: tower::MakeService<(), crate::IncomingRequest> + Send,
73 M::Future: Send,
74 M::Service: crate::service::HttpService,
75 S: http_server_builder::State,
76 S::ServiceFactory: http_server_builder::IsUnset,
77{
78 pub fn tower_make_service_factory(
85 self,
86 tower_make_service: M,
87 ) -> HttpServerBuilder<crate::service::TowerMakeServiceFactory<M, ()>, http_server_builder::SetServiceFactory<S>> {
88 self.service_factory(crate::service::tower_make_service_factory(tower_make_service))
89 }
90}
91
92#[cfg(feature = "tower")]
93#[cfg_attr(docsrs, doc(cfg(feature = "tower")))]
94impl<M, S> HttpServerBuilder<crate::service::TowerMakeServiceWithAddrFactory<M>, S>
95where
96 M: tower::MakeService<SocketAddr, crate::IncomingRequest> + Send,
97 M::Future: Send,
98 M::Service: crate::service::HttpService,
99 S: http_server_builder::State,
100 S::ServiceFactory: http_server_builder::IsUnset,
101{
102 pub fn tower_make_service_with_addr(
109 self,
110 tower_make_service: M,
111 ) -> HttpServerBuilder<crate::service::TowerMakeServiceWithAddrFactory<M>, http_server_builder::SetServiceFactory<S>>
112 {
113 self.service_factory(crate::service::tower_make_service_with_addr_factory(tower_make_service))
114 }
115}
116
117#[cfg(feature = "tower")]
118#[cfg_attr(docsrs, doc(cfg(feature = "tower")))]
119impl<M, T, S> HttpServerBuilder<crate::service::TowerMakeServiceFactory<M, T>, S>
120where
121 M: tower::MakeService<T, crate::IncomingRequest> + Send,
122 M::Future: Send,
123 M::Service: crate::service::HttpService,
124 T: Clone + Send,
125 S: http_server_builder::State,
126 S::ServiceFactory: http_server_builder::IsUnset,
127{
128 pub fn custom_tower_make_service_factory(
135 self,
136 tower_make_service: M,
137 target: T,
138 ) -> HttpServerBuilder<crate::service::TowerMakeServiceFactory<M, T>, http_server_builder::SetServiceFactory<S>> {
139 self.service_factory(crate::service::custom_tower_make_service_factory(tower_make_service, target))
140 }
141}
142
143impl<F> HttpServer<F>
144where
145 F: HttpServiceFactory + Clone + Send + 'static,
146 F::Error: std::error::Error + Send,
147 F::Service: Clone + Send + 'static,
148 <F::Service as HttpService>::Error: std::error::Error + Send + Sync,
149 <F::Service as HttpService>::ResBody: Send,
150 <<F::Service as HttpService>::ResBody as http_body::Body>::Data: Send,
151 <<F::Service as HttpService>::ResBody as http_body::Body>::Error: std::error::Error + Send + Sync,
152{
153 #[cfg(feature = "tls-rustls")]
154 fn set_alpn_protocols(&mut self) {
155 let Some(rustls_config) = &mut self.rustls_config else {
156 return;
157 };
158
159 if rustls_config.alpn_protocols.is_empty() {
161 #[cfg(feature = "http1")]
162 if self.enable_http1 {
163 rustls_config.alpn_protocols.push(b"http/1.0".to_vec());
164 rustls_config.alpn_protocols.push(b"http/1.1".to_vec());
165 }
166
167 #[cfg(feature = "http2")]
168 if self.enable_http2 {
169 rustls_config.alpn_protocols.push(b"h2".to_vec());
170 rustls_config.alpn_protocols.push(b"h2c".to_vec());
171 }
172
173 #[cfg(feature = "http3")]
174 if self.enable_http3 {
175 rustls_config.alpn_protocols.push(b"h3".to_vec());
176 }
177 }
178 }
179
180 pub async fn run(#[allow(unused_mut)] mut self) -> Result<(), HttpError<F>> {
188 #[cfg(feature = "tls-rustls")]
189 self.set_alpn_protocols();
190
191 #[cfg(all(not(any(feature = "http1", feature = "http2")), feature = "tls-rustls"))]
192 let start_tcp_backend = false;
193 #[cfg(all(feature = "http1", not(feature = "http2")))]
194 let start_tcp_backend = self.enable_http1;
195 #[cfg(all(not(feature = "http1"), feature = "http2"))]
196 let start_tcp_backend = self.enable_http2;
197 #[cfg(all(feature = "http1", feature = "http2"))]
198 let start_tcp_backend = self.enable_http1 || self.enable_http2;
199
200 #[cfg(feature = "tls-rustls")]
201 if let Some(_rustls_config) = self.rustls_config {
202 #[cfg(not(feature = "http3"))]
203 let enable_http3 = false;
204 #[cfg(feature = "http3")]
205 let enable_http3 = self.enable_http3;
206
207 match (start_tcp_backend, enable_http3) {
208 #[cfg(feature = "http3")]
209 (false, true) => {
210 let backend = crate::backend::h3::Http3Backend::builder()
211 .ctx(self.ctx)
212 .worker_tasks(self.worker_tasks)
213 .service_factory(self.service_factory)
214 .bind(self.bind)
215 .rustls_config(_rustls_config)
216 .build();
217
218 return backend.run().await;
219 }
220 #[cfg(any(feature = "http1", feature = "http2"))]
221 (true, false) => {
222 let builder = crate::backend::hyper::HyperBackend::builder()
223 .ctx(self.ctx)
224 .worker_tasks(self.worker_tasks)
225 .service_factory(self.service_factory)
226 .bind(self.bind)
227 .rustls_config(_rustls_config);
228
229 #[cfg(feature = "http1")]
230 let builder = builder.http1_enabled(self.enable_http1);
231
232 #[cfg(feature = "http2")]
233 let builder = builder.http2_enabled(self.enable_http2);
234
235 return builder.build().run().await;
236 }
237 #[cfg(all(any(feature = "http1", feature = "http2"), feature = "http3"))]
238 (true, true) => {
239 let builder = crate::backend::hyper::HyperBackend::builder()
240 .ctx(self.ctx.clone())
241 .worker_tasks(self.worker_tasks)
242 .service_factory(self.service_factory.clone())
243 .bind(self.bind)
244 .rustls_config(_rustls_config.clone());
245
246 #[cfg(feature = "http1")]
247 let builder = builder.http1_enabled(self.enable_http1);
248
249 #[cfg(feature = "http2")]
250 let builder = builder.http2_enabled(self.enable_http2);
251
252 let hyper = std::pin::pin!(builder.build().run());
253
254 let http3 = crate::backend::h3::Http3Backend::builder()
255 .ctx(self.ctx)
256 .worker_tasks(self.worker_tasks)
257 .service_factory(self.service_factory)
258 .bind(self.bind)
259 .rustls_config(_rustls_config)
260 .build()
261 .run();
262 let http3 = std::pin::pin!(http3);
263
264 let res = futures::future::select(hyper, http3).await;
265 match res {
266 futures::future::Either::Left((res, _)) => return res,
267 futures::future::Either::Right((res, _)) => return res,
268 }
269 }
270 _ => return Ok(()),
271 }
272
273 }
275
276 #[cfg(any(feature = "http1", feature = "http2"))]
281 if start_tcp_backend {
282 let builder = crate::backend::hyper::HyperBackend::builder()
283 .ctx(self.ctx)
284 .worker_tasks(self.worker_tasks)
285 .service_factory(self.service_factory)
286 .bind(self.bind);
287
288 #[cfg(feature = "http1")]
289 let builder = builder.http1_enabled(self.enable_http1);
290
291 #[cfg(feature = "http2")]
292 let builder = builder.http2_enabled(self.enable_http2);
293
294 return builder.build().run().await;
295 }
296
297 Ok(())
298 }
299}