volga 0.9.1

Easy & Fast Web Framework for Rust
Documentation
//! Extractors for the whole Hosting Environment request

use crate::http::endpoints::args::{
    FromPayload, FromRequestParts, FromRequestRef, Payload, Source,
};
use crate::{HttpRequest, app::HostEnv, error::Error};
use futures_util::future::{Ready, ready};
use hyper::http::{Extensions, request::Parts};

impl TryFrom<&Extensions> for HostEnv {
    type Error = Error;

    #[inline]
    fn try_from(extensions: &Extensions) -> Result<Self, Self::Error> {
        match extensions.get::<HostEnv>() {
            Some(env) => Ok(env.clone()),
            None => Err(Error::server_error(
                "Server Error: hosting environment is not specified",
            )),
        }
    }
}

impl FromRequestRef for HostEnv {
    #[inline]
    fn from_request(req: &HttpRequest) -> Result<Self, Error> {
        req.extensions().try_into()
    }
}

impl FromRequestParts for HostEnv {
    #[inline]
    fn from_parts(parts: &Parts) -> Result<Self, Error> {
        HostEnv::try_from(&parts.extensions)
    }
}

impl FromPayload for HostEnv {
    type Future = Ready<Result<Self, Error>>;

    const SOURCE: Source = Source::Parts;

    #[inline]
    fn from_payload(payload: Payload<'_>) -> Self::Future {
        let Payload::Parts(parts) = payload else {
            unreachable!()
        };
        ready(HostEnv::from_parts(parts))
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::HttpBody;
    use hyper::Request;

    #[test]
    fn it_returns_host_env_when_present_in_extensions() {
        let mut ext = Extensions::new();
        ext.insert(HostEnv::new("root"));

        let result = HostEnv::try_from(&ext).unwrap();
        assert_eq!(result, HostEnv::new("root"));
    }

    #[test]
    fn it_returns_error_when_hostenv_missing_in_extensions() {
        let ext = Extensions::new();
        let err = HostEnv::try_from(&ext).unwrap_err();
        assert_eq!(
            err.to_string(),
            "Server Error: hosting environment is not specified"
        );
    }

    #[test]
    fn it_from_request_ref_extracts_hostenv() {
        let (parts, body) = Request::get("/")
            .extension(HostEnv::new("root"))
            .body(HttpBody::empty())
            .unwrap()
            .into_parts();

        let req = HttpRequest::from_parts(parts, body);

        let result = HostEnv::from_request(&req).unwrap();
        assert_eq!(result, HostEnv::new("root"));
    }

    #[test]
    fn it_from_request_ref_returns_error_when_missing() {
        let (parts, body) = Request::get("/")
            .body(HttpBody::empty())
            .unwrap()
            .into_parts();

        let req = HttpRequest::from_parts(parts, body);

        let err = HostEnv::from_request(&req).unwrap_err();

        assert_eq!(
            err.to_string(),
            "Server Error: hosting environment is not specified"
        );
    }

    #[test]
    fn it_from_parts_extracts_hostenv() {
        let (parts, _) = Request::get("/")
            .extension(HostEnv::new("root"))
            .body(HttpBody::empty())
            .unwrap()
            .into_parts();

        let result = HostEnv::from_parts(&parts).unwrap();
        assert_eq!(result, HostEnv::new("root"));
    }

    #[test]
    fn it_from_parts_returns_error_when_missing() {
        let (parts, _) = Request::get("/")
            .body(HttpBody::empty())
            .unwrap()
            .into_parts();

        let err = HostEnv::from_parts(&parts).unwrap_err();
        assert_eq!(
            err.to_string(),
            "Server Error: hosting environment is not specified"
        );
    }

    #[tokio::test]
    async fn it_from_payload_resolves_correctly() {
        let (parts, _) = Request::get("/")
            .extension(HostEnv::new("root"))
            .body(HttpBody::empty())
            .unwrap()
            .into_parts();

        let result = HostEnv::from_payload(Payload::Parts(&parts)).await.unwrap();
        assert_eq!(result, HostEnv::new("root"));
    }

    #[test]
    fn it_source_returns_parts_variant() {
        assert!(matches!(HostEnv::SOURCE, Source::Parts));
    }
}