requiem_service/
fn_service.rs

1use std::future::Future;
2use std::marker::PhantomData;
3use std::task::{Context, Poll};
4
5use futures_util::future::{ok, Ready};
6
7use crate::{IntoService, IntoServiceFactory, Service, ServiceFactory};
8
9/// Create `ServiceFactory` for function that can act as a `Service`
10pub fn fn_service<F, Fut, Req, Res, Err, Cfg>(
11    f: F,
12) -> FnServiceFactory<F, Fut, Req, Res, Err, Cfg>
13where
14    F: FnMut(Req) -> Fut + Clone,
15    Fut: Future<Output = Result<Res, Err>>,
16{
17    FnServiceFactory::new(f)
18}
19
20/// Create `ServiceFactory` for function that can produce services
21///
22/// # Example
23///
24/// ```rust
25/// use std::io;
26/// use actix_service::{fn_factory, fn_service, Service, ServiceFactory};
27/// use futures_util::future::ok;
28///
29/// /// Service that divides two usize values.
30/// async fn div((x, y): (usize, usize)) -> Result<usize, io::Error> {
31///     if y == 0 {
32///         Err(io::Error::new(io::ErrorKind::Other, "divide by zdro"))
33///     } else {
34///         Ok(x / y)
35///     }
36/// }
37///
38/// #[actix_rt::main]
39/// async fn main() -> io::Result<()> {
40///     // Create service factory that produces `div` services
41///     let factory = fn_factory(|| {
42///         ok::<_, io::Error>(fn_service(div))
43///     });
44///
45///     // construct new service
46///     let mut srv = factory.new_service(()).await?;
47///
48///     // now we can use `div` service
49///     let result = srv.call((10, 20)).await?;
50///
51///     println!("10 / 20 = {}", result);
52///
53///     Ok(())
54/// }
55/// ```
56pub fn fn_factory<F, Cfg, Srv, Fut, Err>(f: F) -> FnServiceNoConfig<F, Cfg, Srv, Fut, Err>
57where
58    Srv: Service,
59    F: Fn() -> Fut,
60    Fut: Future<Output = Result<Srv, Err>>,
61{
62    FnServiceNoConfig::new(f)
63}
64
65/// Create `ServiceFactory` for function that accepts config argument and can produce services
66///
67/// Any function that has following form `Fn(Config) -> Future<Output = Service>` could
68/// act as a `ServiceFactory`.
69///
70/// # Example
71///
72/// ```rust
73/// use std::io;
74/// use actix_service::{fn_factory_with_config, fn_service, Service, ServiceFactory};
75/// use futures_util::future::ok;
76///
77/// #[actix_rt::main]
78/// async fn main() -> io::Result<()> {
79///     // Create service factory. factory uses config argument for
80///     // services it generates.
81///     let factory = fn_factory_with_config(|y: usize| {
82///         ok::<_, io::Error>(fn_service(move |x: usize| ok::<_, io::Error>(x * y)))
83///     });
84///
85///     // construct new service with config argument
86///     let mut srv = factory.new_service(10).await?;
87///
88///     let result = srv.call(10).await?;
89///     assert_eq!(result, 100);
90///
91///     println!("10 * 10 = {}", result);
92///     Ok(())
93/// }
94/// ```
95pub fn fn_factory_with_config<F, Fut, Cfg, Srv, Err>(
96    f: F,
97) -> FnServiceConfig<F, Fut, Cfg, Srv, Err>
98where
99    F: Fn(Cfg) -> Fut,
100    Fut: Future<Output = Result<Srv, Err>>,
101    Srv: Service,
102{
103    FnServiceConfig::new(f)
104}
105
106pub struct FnService<F, Fut, Req, Res, Err>
107where
108    F: FnMut(Req) -> Fut,
109    Fut: Future<Output = Result<Res, Err>>,
110{
111    f: F,
112    _t: PhantomData<Req>,
113}
114
115impl<F, Fut, Req, Res, Err> FnService<F, Fut, Req, Res, Err>
116where
117    F: FnMut(Req) -> Fut,
118    Fut: Future<Output = Result<Res, Err>>,
119{
120    pub(crate) fn new(f: F) -> Self {
121        Self { f, _t: PhantomData }
122    }
123}
124
125impl<F, Fut, Req, Res, Err> Clone for FnService<F, Fut, Req, Res, Err>
126where
127    F: FnMut(Req) -> Fut + Clone,
128    Fut: Future<Output = Result<Res, Err>>,
129{
130    fn clone(&self) -> Self {
131        Self::new(self.f.clone())
132    }
133}
134
135impl<F, Fut, Req, Res, Err> Service for FnService<F, Fut, Req, Res, Err>
136where
137    F: FnMut(Req) -> Fut,
138    Fut: Future<Output = Result<Res, Err>>,
139{
140    type Request = Req;
141    type Response = Res;
142    type Error = Err;
143    type Future = Fut;
144
145    fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
146        Poll::Ready(Ok(()))
147    }
148
149    fn call(&mut self, req: Req) -> Self::Future {
150        (self.f)(req)
151    }
152}
153
154impl<F, Fut, Req, Res, Err> IntoService<FnService<F, Fut, Req, Res, Err>> for F
155where
156    F: FnMut(Req) -> Fut,
157    Fut: Future<Output = Result<Res, Err>>,
158{
159    fn into_service(self) -> FnService<F, Fut, Req, Res, Err> {
160        FnService::new(self)
161    }
162}
163
164pub struct FnServiceFactory<F, Fut, Req, Res, Err, Cfg>
165where
166    F: FnMut(Req) -> Fut,
167    Fut: Future<Output = Result<Res, Err>>,
168{
169    f: F,
170    _t: PhantomData<(Req, Cfg)>,
171}
172
173impl<F, Fut, Req, Res, Err, Cfg> FnServiceFactory<F, Fut, Req, Res, Err, Cfg>
174where
175    F: FnMut(Req) -> Fut + Clone,
176    Fut: Future<Output = Result<Res, Err>>,
177{
178    fn new(f: F) -> Self {
179        FnServiceFactory { f, _t: PhantomData }
180    }
181}
182
183impl<F, Fut, Req, Res, Err, Cfg> Clone for FnServiceFactory<F, Fut, Req, Res, Err, Cfg>
184where
185    F: FnMut(Req) -> Fut + Clone,
186    Fut: Future<Output = Result<Res, Err>>,
187{
188    fn clone(&self) -> Self {
189        Self::new(self.f.clone())
190    }
191}
192
193impl<F, Fut, Req, Res, Err> Service for FnServiceFactory<F, Fut, Req, Res, Err, ()>
194where
195    F: FnMut(Req) -> Fut + Clone,
196    Fut: Future<Output = Result<Res, Err>>,
197{
198    type Request = Req;
199    type Response = Res;
200    type Error = Err;
201    type Future = Fut;
202
203    fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
204        Poll::Ready(Ok(()))
205    }
206
207    fn call(&mut self, req: Self::Request) -> Self::Future {
208        (self.f)(req)
209    }
210}
211
212impl<F, Fut, Req, Res, Err, Cfg> ServiceFactory for FnServiceFactory<F, Fut, Req, Res, Err, Cfg>
213where
214    F: FnMut(Req) -> Fut + Clone,
215    Fut: Future<Output = Result<Res, Err>>,
216{
217    type Request = Req;
218    type Response = Res;
219    type Error = Err;
220
221    type Config = Cfg;
222    type Service = FnService<F, Fut, Req, Res, Err>;
223    type InitError = ();
224    type Future = Ready<Result<Self::Service, Self::InitError>>;
225
226    fn new_service(&self, _: Cfg) -> Self::Future {
227        ok(FnService::new(self.f.clone()))
228    }
229}
230
231impl<F, Fut, Req, Res, Err, Cfg>
232    IntoServiceFactory<FnServiceFactory<F, Fut, Req, Res, Err, Cfg>> for F
233where
234    F: Fn(Req) -> Fut + Clone,
235    Fut: Future<Output = Result<Res, Err>>,
236{
237    fn into_factory(self) -> FnServiceFactory<F, Fut, Req, Res, Err, Cfg> {
238        FnServiceFactory::new(self)
239    }
240}
241
242/// Convert `Fn(&Config) -> Future<Service>` fn to NewService
243pub struct FnServiceConfig<F, Fut, Cfg, Srv, Err>
244where
245    F: Fn(Cfg) -> Fut,
246    Fut: Future<Output = Result<Srv, Err>>,
247    Srv: Service,
248{
249    f: F,
250    _t: PhantomData<(Fut, Cfg, Srv, Err)>,
251}
252
253impl<F, Fut, Cfg, Srv, Err> FnServiceConfig<F, Fut, Cfg, Srv, Err>
254where
255    F: Fn(Cfg) -> Fut,
256    Fut: Future<Output = Result<Srv, Err>>,
257    Srv: Service,
258{
259    fn new(f: F) -> Self {
260        FnServiceConfig { f, _t: PhantomData }
261    }
262}
263
264impl<F, Fut, Cfg, Srv, Err> Clone for FnServiceConfig<F, Fut, Cfg, Srv, Err>
265where
266    F: Fn(Cfg) -> Fut + Clone,
267    Fut: Future<Output = Result<Srv, Err>>,
268    Srv: Service,
269{
270    fn clone(&self) -> Self {
271        FnServiceConfig {
272            f: self.f.clone(),
273            _t: PhantomData,
274        }
275    }
276}
277
278impl<F, Fut, Cfg, Srv, Err> ServiceFactory for FnServiceConfig<F, Fut, Cfg, Srv, Err>
279where
280    F: Fn(Cfg) -> Fut,
281    Fut: Future<Output = Result<Srv, Err>>,
282    Srv: Service,
283{
284    type Request = Srv::Request;
285    type Response = Srv::Response;
286    type Error = Srv::Error;
287
288    type Config = Cfg;
289    type Service = Srv;
290    type InitError = Err;
291    type Future = Fut;
292
293    fn new_service(&self, cfg: Cfg) -> Self::Future {
294        (self.f)(cfg)
295    }
296}
297
298/// Converter for `Fn() -> Future<Service>` fn
299pub struct FnServiceNoConfig<F, C, S, R, E>
300where
301    F: Fn() -> R,
302    S: Service,
303    R: Future<Output = Result<S, E>>,
304{
305    f: F,
306    _t: PhantomData<C>,
307}
308
309impl<F, C, S, R, E> FnServiceNoConfig<F, C, S, R, E>
310where
311    F: Fn() -> R,
312    R: Future<Output = Result<S, E>>,
313    S: Service,
314{
315    fn new(f: F) -> Self {
316        Self { f, _t: PhantomData }
317    }
318}
319
320impl<F, C, S, R, E> ServiceFactory for FnServiceNoConfig<F, C, S, R, E>
321where
322    F: Fn() -> R,
323    R: Future<Output = Result<S, E>>,
324    S: Service,
325{
326    type Request = S::Request;
327    type Response = S::Response;
328    type Error = S::Error;
329    type Service = S;
330    type Config = C;
331    type InitError = E;
332    type Future = R;
333
334    fn new_service(&self, _: C) -> Self::Future {
335        (self.f)()
336    }
337}
338
339impl<F, C, S, R, E> Clone for FnServiceNoConfig<F, C, S, R, E>
340where
341    F: Fn() -> R + Clone,
342    R: Future<Output = Result<S, E>>,
343    S: Service,
344{
345    fn clone(&self) -> Self {
346        Self::new(self.f.clone())
347    }
348}
349
350impl<F, C, S, R, E> IntoServiceFactory<FnServiceNoConfig<F, C, S, R, E>> for F
351where
352    F: Fn() -> R,
353    R: Future<Output = Result<S, E>>,
354    S: Service,
355{
356    fn into_factory(self) -> FnServiceNoConfig<F, C, S, R, E> {
357        FnServiceNoConfig::new(self)
358    }
359}
360
361#[cfg(test)]
362mod tests {
363    use std::task::Poll;
364
365    use futures_util::future::{lazy, ok};
366
367    use super::*;
368    use crate::{Service, ServiceFactory};
369
370    #[actix_rt::test]
371    async fn test_fn_service() {
372        let new_srv = fn_service(|()| ok::<_, ()>("srv"));
373
374        let mut srv = new_srv.new_service(()).await.unwrap();
375        let res = srv.call(()).await;
376        assert_eq!(lazy(|cx| srv.poll_ready(cx)).await, Poll::Ready(Ok(())));
377        assert!(res.is_ok());
378        assert_eq!(res.unwrap(), "srv");
379    }
380
381    #[actix_rt::test]
382    async fn test_fn_service_service() {
383        let mut srv = fn_service(|()| ok::<_, ()>("srv"));
384
385        let res = srv.call(()).await;
386        assert_eq!(lazy(|cx| srv.poll_ready(cx)).await, Poll::Ready(Ok(())));
387        assert!(res.is_ok());
388        assert_eq!(res.unwrap(), "srv");
389    }
390
391    #[actix_rt::test]
392    async fn test_fn_service_with_config() {
393        let new_srv = fn_factory_with_config(|cfg: usize| {
394            ok::<_, ()>(fn_service(move |()| ok::<_, ()>(("srv", cfg))))
395        });
396
397        let mut srv = new_srv.new_service(1).await.unwrap();
398        let res = srv.call(()).await;
399        assert_eq!(lazy(|cx| srv.poll_ready(cx)).await, Poll::Ready(Ok(())));
400        assert!(res.is_ok());
401        assert_eq!(res.unwrap(), ("srv", 1));
402    }
403}