zon_middleware 0.0.6

part of a new WIP, very incomplete async http service stack
Documentation
use http::{Request, Response, StatusCode};
use zon_core::{HttpMiddleware, HttpService};

/// Middleware to override status codes.
///
/// # Example
///
/// ```
/// use http::{Request, Response, StatusCode};
/// use zon_core::{Body, HttpMiddleware, HttpService, IntoHttpService, IntoResponse};
/// use zon_middleware::SetStatus;
///
/// async fn handle(req: Request<Body>) -> Response<Body> {
///     // ...
///     # Response::new(Body::empty())
/// }
///
/// # #[tokio::main]
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// // change the status to `404 Not Found` regardless what the inner service returns
/// let service = SetStatus::new(StatusCode::NOT_FOUND).apply(handle.into_svc());
///
/// // Call the service.
/// let request = Request::builder().body(Body::empty())?;
///
/// let response = HttpService::call(&service, request).await;
///
/// assert_eq!(response.status(), StatusCode::NOT_FOUND);
/// #
/// # Ok(())
/// # }
/// ```
#[derive(Debug, Clone, Copy)]
pub struct SetStatus {
    status: StatusCode,
}

impl SetStatus {
    /// Create a new [`SetStatus`].
    ///
    /// The response status code will be `status` regardless of what the inner
    /// service returns.
    pub fn new(status: StatusCode) -> Self {
        SetStatus { status }
    }
}

impl<S> HttpMiddleware<S> for SetStatus {
    type Service = SetStatusService<S>;

    fn apply(self, inner: S) -> Self::Service {
        SetStatusService::new(inner, self.status)
    }
}

/// Service for [`SetStatus`] middleware.
///
/// See the middleware type for more info.
#[derive(Debug, Clone, Copy)]
pub struct SetStatusService<S> {
    inner: S,
    status: StatusCode,
}

impl<S> SetStatusService<S> {
    /// Create a new [`SetStatusService`].
    ///
    /// The response status code will be `status` regardless of what the inner
    /// service returns.
    pub fn new(inner: S, status: StatusCode) -> Self {
        Self { status, inner }
    }
}

impl<S, ReqBody> HttpService<ReqBody> for SetStatusService<S>
where
    S: HttpService<ReqBody>,
    ReqBody: Send,
{
    type ResponseBody = S::ResponseBody;

    async fn call(&self, req: Request<ReqBody>) -> Response<Self::ResponseBody> {
        let mut response = self.inner.call(req).await;
        *response.status_mut() = self.status;
        response
    }
}