1use std::marker::PhantomData;
2use std::rc::Rc;
3use std::{fmt, net};
4
5use requiem_codec::Framed;
6use requiem_service::{IntoServiceFactory, Service, ServiceFactory};
7
8use crate::body::MessageBody;
9use crate::config::{KeepAlive, ServiceConfig};
10use crate::error::Error;
11use crate::h1::{Codec, ExpectHandler, H1Service, UpgradeHandler};
12use crate::h2::H2Service;
13use crate::helpers::{Data, DataFactory};
14use crate::request::Request;
15use crate::response::Response;
16use crate::service::HttpService;
17
18pub struct HttpServiceBuilder<T, S, X = ExpectHandler, U = UpgradeHandler<T>> {
23 keep_alive: KeepAlive,
24 client_timeout: u64,
25 client_disconnect: u64,
26 secure: bool,
27 local_addr: Option<net::SocketAddr>,
28 expect: X,
29 upgrade: Option<U>,
30 on_connect: Option<Rc<dyn Fn(&T) -> Box<dyn DataFactory>>>,
31 _t: PhantomData<(T, S)>,
32}
33
34impl<T, S> HttpServiceBuilder<T, S, ExpectHandler, UpgradeHandler<T>>
35where
36 S: ServiceFactory<Config = (), Request = Request>,
37 S::Error: Into<Error> + 'static,
38 S::InitError: fmt::Debug,
39 <S::Service as Service>::Future: 'static,
40{
41 pub fn new() -> Self {
43 HttpServiceBuilder {
44 keep_alive: KeepAlive::Timeout(5),
45 client_timeout: 5000,
46 client_disconnect: 0,
47 secure: false,
48 local_addr: None,
49 expect: ExpectHandler,
50 upgrade: None,
51 on_connect: None,
52 _t: PhantomData,
53 }
54 }
55}
56
57impl<T, S, X, U> HttpServiceBuilder<T, S, X, U>
58where
59 S: ServiceFactory<Config = (), Request = Request>,
60 S::Error: Into<Error> + 'static,
61 S::InitError: fmt::Debug,
62 <S::Service as Service>::Future: 'static,
63 X: ServiceFactory<Config = (), Request = Request, Response = Request>,
64 X::Error: Into<Error>,
65 X::InitError: fmt::Debug,
66 <X::Service as Service>::Future: 'static,
67 U: ServiceFactory<Config = (), Request = (Request, Framed<T, Codec>), Response = ()>,
68 U::Error: fmt::Display,
69 U::InitError: fmt::Debug,
70 <U::Service as Service>::Future: 'static,
71{
72 pub fn keep_alive<W: Into<KeepAlive>>(mut self, val: W) -> Self {
76 self.keep_alive = val.into();
77 self
78 }
79
80 pub fn secure(mut self) -> Self {
82 self.secure = true;
83 self
84 }
85
86 pub fn local_addr(mut self, addr: net::SocketAddr) -> Self {
88 self.local_addr = Some(addr);
89 self
90 }
91
92 pub fn client_timeout(mut self, val: u64) -> Self {
102 self.client_timeout = val;
103 self
104 }
105
106 pub fn client_disconnect(mut self, val: u64) -> Self {
115 self.client_disconnect = val;
116 self
117 }
118
119 pub fn expect<F, X1>(self, expect: F) -> HttpServiceBuilder<T, S, X1, U>
125 where
126 F: IntoServiceFactory<X1>,
127 X1: ServiceFactory<Config = (), Request = Request, Response = Request>,
128 X1::Error: Into<Error>,
129 X1::InitError: fmt::Debug,
130 <X1::Service as Service>::Future: 'static,
131 {
132 HttpServiceBuilder {
133 keep_alive: self.keep_alive,
134 client_timeout: self.client_timeout,
135 client_disconnect: self.client_disconnect,
136 secure: self.secure,
137 local_addr: self.local_addr,
138 expect: expect.into_factory(),
139 upgrade: self.upgrade,
140 on_connect: self.on_connect,
141 _t: PhantomData,
142 }
143 }
144
145 pub fn upgrade<F, U1>(self, upgrade: F) -> HttpServiceBuilder<T, S, X, U1>
150 where
151 F: IntoServiceFactory<U1>,
152 U1: ServiceFactory<
153 Config = (),
154 Request = (Request, Framed<T, Codec>),
155 Response = (),
156 >,
157 U1::Error: fmt::Display,
158 U1::InitError: fmt::Debug,
159 <U1::Service as Service>::Future: 'static,
160 {
161 HttpServiceBuilder {
162 keep_alive: self.keep_alive,
163 client_timeout: self.client_timeout,
164 client_disconnect: self.client_disconnect,
165 secure: self.secure,
166 local_addr: self.local_addr,
167 expect: self.expect,
168 upgrade: Some(upgrade.into_factory()),
169 on_connect: self.on_connect,
170 _t: PhantomData,
171 }
172 }
173
174 pub fn on_connect<F, I>(mut self, f: F) -> Self
179 where
180 F: Fn(&T) -> I + 'static,
181 I: Clone + 'static,
182 {
183 self.on_connect = Some(Rc::new(move |io| Box::new(Data(f(io)))));
184 self
185 }
186
187 pub fn h1<F, B>(self, service: F) -> H1Service<T, S, B, X, U>
189 where
190 B: MessageBody,
191 F: IntoServiceFactory<S>,
192 S::Error: Into<Error>,
193 S::InitError: fmt::Debug,
194 S::Response: Into<Response<B>>,
195 {
196 let cfg = ServiceConfig::new(
197 self.keep_alive,
198 self.client_timeout,
199 self.client_disconnect,
200 self.secure,
201 self.local_addr,
202 );
203 H1Service::with_config(cfg, service.into_factory())
204 .expect(self.expect)
205 .upgrade(self.upgrade)
206 .on_connect(self.on_connect)
207 }
208
209 pub fn h2<F, B>(self, service: F) -> H2Service<T, S, B>
211 where
212 B: MessageBody + 'static,
213 F: IntoServiceFactory<S>,
214 S::Error: Into<Error> + 'static,
215 S::InitError: fmt::Debug,
216 S::Response: Into<Response<B>> + 'static,
217 <S::Service as Service>::Future: 'static,
218 {
219 let cfg = ServiceConfig::new(
220 self.keep_alive,
221 self.client_timeout,
222 self.client_disconnect,
223 self.secure,
224 self.local_addr,
225 );
226 H2Service::with_config(cfg, service.into_factory()).on_connect(self.on_connect)
227 }
228
229 pub fn finish<F, B>(self, service: F) -> HttpService<T, S, B, X, U>
231 where
232 B: MessageBody + 'static,
233 F: IntoServiceFactory<S>,
234 S::Error: Into<Error> + 'static,
235 S::InitError: fmt::Debug,
236 S::Response: Into<Response<B>> + 'static,
237 <S::Service as Service>::Future: 'static,
238 {
239 let cfg = ServiceConfig::new(
240 self.keep_alive,
241 self.client_timeout,
242 self.client_disconnect,
243 self.secure,
244 self.local_addr,
245 );
246 HttpService::with_config(cfg, service.into_factory())
247 .expect(self.expect)
248 .upgrade(self.upgrade)
249 .on_connect(self.on_connect)
250 }
251}