1use core::{fmt, marker::PhantomData};
2
3use xitca_io::net;
4use xitca_service::Service;
5
6use super::{
7 config::{DEFAULT_HEADER_LIMIT, DEFAULT_READ_BUF_LIMIT, DEFAULT_WRITE_BUF_LIMIT, HttpServiceConfig},
8 service::HttpService,
9 tls,
10};
11
12#[doc(hidden)]
15pub(crate) mod marker {
16 pub struct Http;
18 #[cfg(feature = "http1")]
19 pub struct Http1;
20 #[cfg(feature = "http2")]
21 pub struct Http2;
22
23 pub struct Poll;
25 #[cfg(feature = "io-uring")]
26 pub struct Uring;
27}
28
29pub struct HttpServiceBuilder<
32 V,
33 Io,
34 St,
35 FA,
36 const HEADER_LIMIT: usize,
37 const READ_BUF_LIMIT: usize,
38 const WRITE_BUF_LIMIT: usize,
39> {
40 pub(crate) tls_factory: FA,
41 pub(crate) config: HttpServiceConfig<HEADER_LIMIT, READ_BUF_LIMIT, WRITE_BUF_LIMIT>,
42 pub(crate) _body: PhantomData<fn(V, Io, St)>,
43}
44
45impl
46 HttpServiceBuilder<
47 marker::Http,
48 marker::Poll,
49 net::Stream,
50 tls::NoOpTlsAcceptorBuilder,
51 DEFAULT_HEADER_LIMIT,
52 DEFAULT_READ_BUF_LIMIT,
53 DEFAULT_WRITE_BUF_LIMIT,
54 >
55{
56 pub const fn new() -> Self {
58 Self::with_config(HttpServiceConfig::new())
59 }
60
61 pub const fn with_config<const HEADER_LIMIT: usize, const READ_BUF_LIMIT: usize, const WRITE_BUF_LIMIT: usize>(
63 config: HttpServiceConfig<HEADER_LIMIT, READ_BUF_LIMIT, WRITE_BUF_LIMIT>,
64 ) -> HttpServiceBuilder<
65 marker::Http,
66 marker::Poll,
67 net::Stream,
68 tls::NoOpTlsAcceptorBuilder,
69 HEADER_LIMIT,
70 READ_BUF_LIMIT,
71 WRITE_BUF_LIMIT,
72 > {
73 HttpServiceBuilder {
74 tls_factory: tls::NoOpTlsAcceptorBuilder,
75 config,
76 _body: PhantomData,
77 }
78 }
79
80 #[cfg(feature = "http1")]
81 pub fn h1() -> HttpServiceBuilder<
83 marker::Http1,
84 marker::Poll,
85 net::TcpStream,
86 tls::NoOpTlsAcceptorBuilder,
87 DEFAULT_HEADER_LIMIT,
88 DEFAULT_READ_BUF_LIMIT,
89 DEFAULT_WRITE_BUF_LIMIT,
90 > {
91 HttpServiceBuilder {
92 tls_factory: tls::NoOpTlsAcceptorBuilder,
93 config: HttpServiceConfig::default(),
94 _body: PhantomData,
95 }
96 }
97
98 #[cfg(feature = "http2")]
99 pub fn h2() -> HttpServiceBuilder<
101 marker::Http2,
102 marker::Poll,
103 net::TcpStream,
104 tls::NoOpTlsAcceptorBuilder,
105 DEFAULT_HEADER_LIMIT,
106 DEFAULT_READ_BUF_LIMIT,
107 DEFAULT_WRITE_BUF_LIMIT,
108 > {
109 HttpServiceBuilder {
110 tls_factory: tls::NoOpTlsAcceptorBuilder,
111 config: HttpServiceConfig::default(),
112 _body: PhantomData,
113 }
114 }
115
116 #[cfg(feature = "http3")]
117 pub fn h3() -> super::h3::H3ServiceBuilder {
119 super::h3::H3ServiceBuilder::new()
120 }
121}
122
123#[cfg(feature = "io-uring")]
124impl<St, FA, const HEADER_LIMIT: usize, const READ_BUF_LIMIT: usize, const WRITE_BUF_LIMIT: usize>
125 HttpServiceBuilder<marker::Http, marker::Poll, St, FA, HEADER_LIMIT, READ_BUF_LIMIT, WRITE_BUF_LIMIT>
126{
127 pub fn io_uring(
129 self,
130 ) -> HttpServiceBuilder<marker::Http, marker::Uring, St, FA, HEADER_LIMIT, READ_BUF_LIMIT, WRITE_BUF_LIMIT> {
131 HttpServiceBuilder {
132 tls_factory: self.tls_factory,
133 config: self.config,
134 _body: PhantomData,
135 }
136 }
137}
138
139impl<V, Io, St, FA, const HEADER_LIMIT: usize, const READ_BUF_LIMIT: usize, const WRITE_BUF_LIMIT: usize>
140 HttpServiceBuilder<V, Io, St, FA, HEADER_LIMIT, READ_BUF_LIMIT, WRITE_BUF_LIMIT>
141{
142 pub fn config<const HEADER_LIMIT_2: usize, const READ_BUF_LIMIT_2: usize, const WRITE_BUF_LIMIT_2: usize>(
144 self,
145 config: HttpServiceConfig<HEADER_LIMIT_2, READ_BUF_LIMIT_2, WRITE_BUF_LIMIT_2>,
146 ) -> HttpServiceBuilder<V, Io, St, FA, HEADER_LIMIT_2, READ_BUF_LIMIT_2, WRITE_BUF_LIMIT_2> {
147 HttpServiceBuilder {
148 tls_factory: self.tls_factory,
149 config,
150 _body: PhantomData,
151 }
152 }
153
154 pub fn with_tls<TlsF>(
156 self,
157 tls_factory: TlsF,
158 ) -> HttpServiceBuilder<V, Io, St, TlsF, HEADER_LIMIT, READ_BUF_LIMIT, WRITE_BUF_LIMIT> {
159 HttpServiceBuilder {
160 tls_factory,
161 config: self.config,
162 _body: PhantomData,
163 }
164 }
165 #[cfg(feature = "openssl")]
166 pub fn openssl(
168 self,
169 acceptor: tls::openssl::TlsAcceptor,
170 ) -> HttpServiceBuilder<V, Io, St, tls::openssl::TlsAcceptorBuilder, HEADER_LIMIT, READ_BUF_LIMIT, WRITE_BUF_LIMIT>
171 {
172 self.with_tls(tls::openssl::TlsAcceptorBuilder::new(acceptor))
173 }
174
175 #[cfg(feature = "rustls")]
176 pub fn rustls(
178 self,
179 config: tls::rustls::RustlsConfig,
180 ) -> HttpServiceBuilder<V, Io, St, tls::rustls::TlsAcceptorBuilder, HEADER_LIMIT, READ_BUF_LIMIT, WRITE_BUF_LIMIT>
181 {
182 self.with_tls(tls::rustls::TlsAcceptorBuilder::new(config))
183 }
184
185 #[cfg(feature = "native-tls")]
186 pub fn native_tls(
188 self,
189 acceptor: tls::native_tls::TlsAcceptor,
190 ) -> HttpServiceBuilder<V, Io, St, tls::native_tls::TlsAcceptorBuilder, HEADER_LIMIT, READ_BUF_LIMIT, WRITE_BUF_LIMIT>
191 {
192 self.with_tls(tls::native_tls::TlsAcceptorBuilder::new(acceptor))
193 }
194}
195
196type Error = Box<dyn fmt::Debug>;
197
198impl<FA, Io, S, E, const HEADER_LIMIT: usize, const READ_BUF_LIMIT: usize, const WRITE_BUF_LIMIT: usize>
199 Service<Result<S, E>>
200 for HttpServiceBuilder<marker::Http, Io, net::Stream, FA, HEADER_LIMIT, READ_BUF_LIMIT, WRITE_BUF_LIMIT>
201where
202 FA: Service,
203 FA::Error: fmt::Debug + 'static,
204 E: fmt::Debug + 'static,
205{
206 type Response =
207 HttpService<marker::Http, Io, net::Stream, S, FA::Response, HEADER_LIMIT, READ_BUF_LIMIT, WRITE_BUF_LIMIT>;
208 type Error = Error;
209
210 async fn call(&self, res: Result<S, E>) -> Result<Self::Response, Self::Error> {
211 let service = res.map_err(|e| Box::new(e) as Error)?;
212 let tls_acceptor = self.tls_factory.call(()).await.map_err(|e| Box::new(e) as Error)?;
213 Ok(HttpService::new(self.config, service, tls_acceptor))
214 }
215}