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}