grillon/
response.rs

1//! The `response` module provides everything to implement custom responses that can
2//! be asserted with [`Assert`].
3//!
4//! [`Grillon`] provides a default implementation of [`Response`] with [`Hyper`](https://github.com/hyperium/hyper).
5//!
6//! [`Assert`]: crate::Assert
7//! [`Grillon`]: crate::Grillon
8use futures::{future::LocalBoxFuture, FutureExt};
9use http::{HeaderMap, StatusCode};
10use reqwest::Response as ReqwestResponse;
11use serde_json::Value;
12
13/// A generic http response representation with
14/// convenience methods for subsequent assertions
15/// with [`Assert`].
16///
17/// [`Assert`]: crate::Assert
18pub trait Response {
19    /// Returns the http status code.
20    fn status(&self) -> StatusCode;
21    /// Returns a future with the response json body.
22    fn json<'a>(self) -> LocalBoxFuture<'a, Option<Value>>;
23    /// Returns the response headers.
24    fn headers(&self) -> HeaderMap;
25}
26
27impl Response for ReqwestResponse {
28    fn status(&self) -> StatusCode {
29        self.status()
30    }
31
32    fn json<'a>(self) -> LocalBoxFuture<'a, Option<Value>> {
33        async move {
34            if let Ok(bytes) = self.bytes().await {
35                if bytes.is_empty() {
36                    return None;
37                }
38                let json: Value = serde_json::from_slice(&bytes).expect("Failed to decode json");
39
40                Some(json)
41            } else {
42                None
43            }
44        }
45        .boxed_local()
46    }
47
48    fn headers(&self) -> HeaderMap {
49        self.headers().clone()
50    }
51}