asserhttp 0.7.1

Fluent http response assertions
Documentation
use super::accessor::{BodyAccessor, HeaderAccessor, StatusAccessor};
use crate::{header::key::HeaderKey, AsserhttpError, AsserhttpResult};

type ActixResponse = actix_web::HttpResponse<actix_http::body::BoxBody>;
type ActixServiceResponse = actix_web::dev::ServiceResponse;

impl StatusAccessor for ActixResponse {
    fn get_status(&self) -> u16 {
        self.status().as_u16()
    }
}

impl StatusAccessor for ActixServiceResponse {
    fn get_status(&self) -> u16 {
        self.status().as_u16()
    }
}

impl HeaderAccessor for ActixResponse {
    fn get_keys(&self) -> Vec<HeaderKey> {
        self.headers().iter().map(|(k, _)| k.as_str().into()).collect::<Vec<_>>()
    }

    fn get_raw_values(&self, key: &HeaderKey) -> Vec<String> {
        let value = self
            .headers()
            .get(key.as_ref())
            .and_then(|v| v.to_str().ok())
            .map(str::to_string)
            .unwrap();
        vec![value]
    }
}

impl HeaderAccessor for ActixServiceResponse {
    fn get_keys(&self) -> Vec<HeaderKey> {
        self.headers().iter().map(|(k, _)| k.as_str().into()).collect::<Vec<_>>()
    }

    fn get_raw_values(&self, key: &HeaderKey) -> Vec<String> {
        let value = self
            .headers()
            .get(key.as_ref())
            .and_then(|v| v.to_str().ok())
            .map(str::to_string)
            .unwrap();
        vec![value]
    }
}

impl BodyAccessor for ActixResponse {
    fn get_bytes(&mut self) -> AsserhttpResult<Vec<u8>> {
        body_bytes(self)
    }
}

impl BodyAccessor for ActixServiceResponse {
    fn get_bytes(&mut self) -> AsserhttpResult<Vec<u8>> {
        body_bytes(self.response_mut())
    }
}

fn body_bytes(original: &mut ActixResponse) -> AsserhttpResult<Vec<u8>> {
    let mut resp_cpy = ActixResponse::build(original.status());
    original.headers().iter().for_each(|h| {
        resp_cpy.insert_header(h);
    });
    let mut resp_cpy = resp_cpy.finish();
    std::mem::swap(original, &mut resp_cpy);
    let (_, body) = resp_cpy.into_parts();
    use actix_http::body::MessageBody as _;
    let buf = body
        .try_into_bytes()
        .map(|b| b.to_vec())
        .map_err(|_| AsserhttpError::HttpError("Could not read actix response body".to_string()))?;
    if buf.is_empty() {
        return Err(AsserhttpError::BodyAbsent);
    }
    Ok(buf)
}