1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
//! utilities for testing web application

use core::{future::poll_fn, pin::pin};

use futures_core::stream::Stream;

use crate::service::pipeline::PipelineE;

/// Collect request or response body to Vec.
pub async fn collect_body<B, T, E>(body: B) -> Result<Vec<u8>, E>
where
    B: Stream<Item = Result<T, E>>,
    T: AsRef<[u8]>,
{
    let mut body = pin!(body);

    let mut res = Vec::new();

    while let Some(chunk) = poll_fn(|cx| body.as_mut().poll_next(cx)).await {
        res.extend_from_slice(chunk?.as_ref());
    }

    Ok(res)
}

pub type CollectStringError<E> = PipelineE<std::string::FromUtf8Error, E>;

/// Collect request or response body and parse it to String.
pub async fn collect_string_body<B, T, E>(body: B) -> Result<String, CollectStringError<E>>
where
    B: Stream<Item = Result<T, E>>,
    T: AsRef<[u8]>,
{
    let body = collect_body(body).await.map_err(CollectStringError::Second)?;
    String::from_utf8(body).map_err(CollectStringError::First)
}