axum-starter 0.11.0

A help crate for simplify the code of starting a axum server
Documentation
use axum::BoxError;
use bytes::Bytes;
use futures::{future::ok, TryStreamExt};
use http::{response::Parts, Response};
use http_body::Body;
use http_body_util::combinators::UnsyncBoxBody;
use serde::de::DeserializeOwned;
use tap::Tap;

pub struct TestResponse {
    parts: Parts,
    payload: axum::body::Body,
}

impl TestResponse {
    pub fn new<R>(resp: Response<R>) -> Self
    where
        R: http_body::Body<Data = Bytes> + Send + 'static,
        R::Error: Into<BoxError>,
    {
        let (parts, body) = resp.into_parts();
        let payload = axum::body::Body::new(UnsyncBoxBody::new(body));

        Self { parts, payload }
    }

    pub fn parts(self) -> Parts {
        self.parts
    }

    pub async fn bytes(self) -> Result<Bytes, axum::Error> {
        let size = self.payload.size_hint().lower() as _;
        let ret = self
            .payload
            .into_data_stream()
            .try_fold(Vec::with_capacity(size), |buff, chunk| {
                ok(buff.tap_mut(|buff| buff.extend(chunk)))
            })
            .await
            .expect("Error");

        Ok(Bytes::from(ret))
    }

    pub async fn plain(self) -> Result<String, axum::Error> {
        let bytes = self.bytes().await?;
        String::from_utf8(bytes.to_vec()).map_err(axum::Error::new)
    }

    pub async fn json<T: DeserializeOwned>(self) -> Result<T, axum::Error> {
        let bytes = self.bytes().await?;
        let reader = std::io::Cursor::new(bytes);
        serde_json::from_reader(reader).map_err(axum::Error::new)
    }
}