scuffle_http/service/
mod.rs

1use std::future::Future;
2use std::net::SocketAddr;
3
4use crate::IncomingRequest;
5
6mod clone_factory;
7mod function;
8#[cfg(feature = "tower")]
9#[cfg_attr(docsrs, doc(cfg(feature = "tower")))]
10mod tower_factory;
11
12pub use clone_factory::*;
13pub use function::*;
14#[cfg(feature = "tower")]
15#[cfg_attr(docsrs, doc(cfg(feature = "tower")))]
16pub use tower_factory::*;
17
18/// A trait representing an HTTP service.
19///
20/// This trait must be used in combination with [`HttpServiceFactory`].
21/// It is very similar to tower's service trait and implemented
22/// for all types that implement [`tower::Service<IncomingRequest>`](https://docs.rs/tower/latest/tower/trait.Service.html).
23pub trait HttpService {
24    type Error;
25    type ResBody: http_body::Body;
26
27    /// Handle an incoming request.
28    ///
29    /// This method is called for each incoming request.
30    /// The service must return a response for the given request.
31    fn call(
32        &mut self,
33        req: IncomingRequest,
34    ) -> impl Future<Output = Result<http::Response<Self::ResBody>, Self::Error>> + Send;
35}
36
37// Implement for tower services
38#[cfg(feature = "tower")]
39#[cfg_attr(docsrs, doc(cfg(feature = "tower")))]
40impl<T, B> HttpService for T
41where
42    T: tower::Service<IncomingRequest, Response = http::Response<B>> + Send,
43    T::Future: Send,
44    B: http_body::Body,
45{
46    type Error = T::Error;
47    type ResBody = B;
48
49    async fn call(&mut self, req: IncomingRequest) -> Result<http::Response<Self::ResBody>, Self::Error> {
50        // wait for the tower service to be ready
51        futures::future::poll_fn(|cx| self.poll_ready(cx)).await?;
52
53        self.call(req).await
54    }
55}
56
57/// A trait representing an HTTP service factory.
58///
59/// This trait must be implemented by types that can create new instances of [`HttpService`].
60/// It is conceptually similar to tower's [`MakeService`](https://docs.rs/tower/latest/tower/trait.MakeService.html) trait.
61///
62/// It is intended to create a new service for each incoming connection.
63/// If you don't need to implement any custom factory logic, you can use [`ServiceCloneFactory`] to make a factory that clones the given service for each new connection.
64pub trait HttpServiceFactory {
65    type Error;
66    type Service: HttpService;
67
68    /// Create a new service for a new connection.
69    ///
70    /// `remote_addr` is the address of the connecting remote peer.
71    fn new_service(&mut self, remote_addr: SocketAddr) -> impl Future<Output = Result<Self::Service, Self::Error>> + Send;
72}