mock_http_connector/response/
mod.rs

1mod future;
2pub use future::{IntoResponseFuture, ResponseFuture};
3
4use crate::error::BoxError;
5use crate::hyper::{header, Response, StatusCode};
6use std::error::Error as StdError;
7
8/// Trait for values that can be transformed into `Result<Response<String>, BoxError>`
9///
10/// All implementations of this trait can be used as the return type for the future passed to
11/// [`crate::CaseBuilder::returning`].
12///
13/// ## Examples
14///
15/// ### String-types
16///
17/// String-types will use their value as the response body, with a status code of `200`.
18///
19/// ```rust
20/// # use mock_http_connector::IntoResponse;
21/// // &str
22/// let some_str = "some_str";
23/// let res = some_str.into_response();
24///
25/// // Static
26/// let some_string = "some_string".to_string();
27/// let res = some_string.into_response();
28/// ```
29///
30/// ### Status and string-types
31///
32/// You can pass a status code by passing a value that implements `TryInto<StatusCode>`.
33///
34/// ```rust
35/// # use mock_http_connector::IntoResponse;
36/// let status = 400;
37/// let body = "FILE NOT FOUND";
38/// let res = (status, body).into_response();
39/// ```
40///
41#[cfg_attr(
42    feature = "json",
43    doc = r##"
44### JSON payloads
45
46This is only supported when the `json` feature flag is set.
47
48```rust
49# use mock_http_connector::IntoResponse;
50# use serde_json::json;
51let payload = json!({ "message": "some response" });
52let res = payload.into_response();
53```
54"##
55)]
56pub trait IntoResponse {
57    /// Transforms self into a `Result<Response<String>, BoxError>`
58    fn into_response(self) -> Result<Response<String>, BoxError>;
59}
60
61impl<R, E> IntoResponse for Result<R, E>
62where
63    R: IntoResponse,
64    E: StdError + Send + Sync + 'static,
65{
66    fn into_response(self) -> Result<Response<String>, BoxError> {
67        self.map_err(Into::into).and_then(|r| r.into_response())
68    }
69}
70
71impl<B> IntoResponse for Response<B>
72where
73    B: ToString,
74{
75    fn into_response(self) -> Result<Response<String>, BoxError> {
76        Ok(self.map(|b| b.to_string()))
77    }
78}
79
80impl IntoResponse for &'_ str {
81    fn into_response(self) -> Result<Response<String>, BoxError> {
82        Ok(Response::builder()
83            .status(StatusCode::OK)
84            .body(self.to_string())?)
85    }
86}
87
88impl IntoResponse for String {
89    fn into_response(self) -> Result<Response<String>, BoxError> {
90        Ok(Response::builder().status(StatusCode::OK).body(self)?)
91    }
92}
93
94impl<S, B> IntoResponse for (S, B)
95where
96    S: TryInto<StatusCode> + 'static,
97    S::Error: StdError + Send + Sync + 'static,
98    B: ToString + 'static,
99{
100    fn into_response(self) -> Result<Response<String>, BoxError> {
101        let status = self.0.try_into();
102        let body = self.1.to_string();
103        Ok(Response::builder().status(status?).body(body)?)
104    }
105}
106
107#[cfg(feature = "json")]
108impl IntoResponse for serde_json::Value {
109    fn into_response(self) -> Result<Response<String>, BoxError> {
110        Ok(Response::builder()
111            .status(StatusCode::OK)
112            .header(header::CONTENT_TYPE, "application/json")
113            .body(serde_json::to_string(&self)?)?)
114    }
115}