faucet-server 2.1.0

Welcome to Faucet, your go-to solution for deploying Plumber APIs and Shiny Applications with blazing speed and efficiency. Faucet is a high-performance server built with Rust, offering Round Robin and Round Robin + IP Hash load balancing for seamless scaling and distribution of your R applications. Whether you're a data scientist, developer, or DevOps enthusiast, Faucet streamlines the deployment process, making it easier than ever to manage replicas and balance loads effectively.
Documentation
use std::net::IpAddr;

pub trait Service<Request>: Send + Sync {
    type Response;
    type Error;
    fn call(
        &self,
        req: Request,
        ip_addr: Option<IpAddr>,
    ) -> impl std::future::Future<Output = Result<Self::Response, Self::Error>>;
}

pub trait Layer<S> {
    type Service;
    fn layer(&self, inner: S) -> Self::Service;
}

pub struct ServiceBuilder<S> {
    service: S,
}

impl<S> ServiceBuilder<S> {
    pub fn new(service: S) -> Self {
        ServiceBuilder { service }
    }
    pub fn layer<L>(self, layer: L) -> ServiceBuilder<L::Service>
    where
        L: Layer<S>,
    {
        ServiceBuilder::new(layer.layer(self.service))
    }
    pub fn build(self) -> S {
        self.service
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[tokio::test]
    async fn basic_service_response() {
        struct Svc;

        impl Service<()> for Svc {
            type Response = String;
            type Error = ();
            async fn call(&self, _: (), _: Option<IpAddr>) -> Result<Self::Response, Self::Error> {
                Ok("Hello, world!".to_string())
            }
        }

        let svc = ServiceBuilder::new(Svc).build();

        assert_eq!(svc.call((), None).await.unwrap(), "Hello, world!");
    }

    #[tokio::test]
    async fn basic_service_middleware() {
        struct Svc;

        impl Service<&'static str> for Svc {
            type Response = String;
            type Error = ();
            async fn call(
                &self,
                _: &'static str,
                _: Option<IpAddr>,
            ) -> Result<Self::Response, Self::Error> {
                Ok("Hello, world!".to_string())
            }
        }

        struct GoodByeService<S> {
            inner: S,
        }

        impl<S> Service<&'static str> for GoodByeService<S>
        where
            S: Service<&'static str, Response = String, Error = ()>,
        {
            type Response = String;
            type Error = ();
            async fn call(
                &self,
                req: &'static str,
                _: Option<IpAddr>,
            ) -> Result<Self::Response, Self::Error> {
                if req == "Goodbye" {
                    Ok("Goodbye, world!".to_string())
                } else {
                    self.inner.call(req, None).await
                }
            }
        }

        struct GoodByeLayer;

        impl<S> Layer<S> for GoodByeLayer {
            type Service = GoodByeService<S>;
            fn layer(&self, inner: S) -> Self::Service {
                GoodByeService { inner }
            }
        }

        let svc = ServiceBuilder::new(Svc).layer(GoodByeLayer).build();

        assert_eq!(svc.call("Goodbye", None).await.unwrap(), "Goodbye, world!");
        assert_eq!(svc.call("Hello", None).await.unwrap(), "Hello, world!");
    }

    #[tokio::test]
    async fn multiple_layer_middleware() {
        struct Svc;

        impl Service<&'static str> for Svc {
            type Response = String;
            type Error = ();
            async fn call(
                &self,
                _: &'static str,
                _: Option<IpAddr>,
            ) -> Result<Self::Response, Self::Error> {
                Ok("Hello, world!".to_string())
            }
        }

        struct GoodByeService<S> {
            inner: S,
        }

        impl<S> Service<&'static str> for GoodByeService<S>
        where
            S: Service<&'static str, Response = String, Error = ()>,
        {
            type Response = String;
            type Error = ();
            async fn call(
                &self,
                req: &'static str,
                _: Option<IpAddr>,
            ) -> Result<Self::Response, Self::Error> {
                if req == "Goodbye" {
                    Ok("Goodbye, world!".to_string())
                } else {
                    self.inner.call(req, None).await
                }
            }
        }

        struct GoodByeLayer;

        impl<S> Layer<S> for GoodByeLayer {
            type Service = GoodByeService<S>;
            fn layer(&self, inner: S) -> Self::Service {
                GoodByeService { inner }
            }
        }

        struct HowAreYouService<S> {
            inner: S,
        }

        impl<S> Service<&'static str> for HowAreYouService<S>
        where
            S: Service<&'static str, Response = String, Error = ()>,
        {
            type Response = String;
            type Error = ();
            async fn call(
                &self,
                req: &'static str,
                _: Option<IpAddr>,
            ) -> Result<Self::Response, Self::Error> {
                if req == "How are you?" {
                    Ok("I'm fine, thank you!".to_string())
                } else {
                    self.inner.call(req, None).await
                }
            }
        }

        struct HowAreYouLayer;

        impl<S> Layer<S> for HowAreYouLayer {
            type Service = HowAreYouService<S>;
            fn layer(&self, inner: S) -> Self::Service {
                HowAreYouService { inner }
            }
        }

        let svc = ServiceBuilder::new(Svc)
            .layer(GoodByeLayer)
            .layer(HowAreYouLayer)
            .build();

        assert_eq!(svc.call("Goodbye", None).await.unwrap(), "Goodbye, world!");
        assert_eq!(svc.call("Hello", None).await.unwrap(), "Hello, world!");
        assert_eq!(
            svc.call("How are you?", None).await.unwrap(),
            "I'm fine, thank you!"
        );
    }
}