use http::{HeaderMap, HeaderName, HeaderValue, Response, StatusCode};
use http_body_util::Full;
use hyper::body::Bytes;
use serde::Serialize;
use std::convert::TryInto;
use std::time::Duration;
#[derive(Clone, Debug)]
pub struct ResponseTemplate {
mime: String,
status_code: StatusCode,
headers: HeaderMap,
body: Option<Vec<u8>>,
delay: Option<Duration>,
}
impl ResponseTemplate {
pub fn new<S>(s: S) -> Self
where
S: TryInto<StatusCode>,
<S as TryInto<StatusCode>>::Error: std::fmt::Debug,
{
let status_code = s.try_into().expect("Failed to convert into status code.");
Self {
status_code,
headers: HeaderMap::new(),
mime: String::new(),
body: None,
delay: None,
}
}
pub fn append_header<K, V>(mut self, key: K, value: V) -> Self
where
K: TryInto<HeaderName>,
<K as TryInto<HeaderName>>::Error: std::fmt::Debug,
V: TryInto<HeaderValue>,
<V as TryInto<HeaderValue>>::Error: std::fmt::Debug,
{
let key = key.try_into().expect("Failed to convert into header name.");
let value = value
.try_into()
.expect("Failed to convert into header value.");
self.headers.append(key, value);
self
}
pub fn insert_header<K, V>(mut self, key: K, value: V) -> Self
where
K: TryInto<HeaderName>,
<K as TryInto<HeaderName>>::Error: std::fmt::Debug,
V: TryInto<HeaderValue>,
<V as TryInto<HeaderValue>>::Error: std::fmt::Debug,
{
let key = key.try_into().expect("Failed to convert into header name.");
let value = value
.try_into()
.expect("Failed to convert into header value.");
self.headers.insert(key, value);
self
}
pub fn append_headers<K, V, I>(mut self, headers: I) -> Self
where
K: TryInto<HeaderName>,
<K as TryInto<HeaderName>>::Error: std::fmt::Debug,
V: TryInto<HeaderValue>,
<V as TryInto<HeaderValue>>::Error: std::fmt::Debug,
I: IntoIterator<Item = (K, V)>,
{
let headers = headers.into_iter().map(|(key, value)| {
(
key.try_into().expect("Failed to convert into header name."),
value
.try_into()
.expect("Failed to convert into header value."),
)
});
self.headers.extend(headers);
self
}
pub fn set_body_bytes<B>(mut self, body: B) -> Self
where
B: TryInto<Vec<u8>>,
<B as TryInto<Vec<u8>>>::Error: std::fmt::Debug,
{
let body = body.try_into().expect("Failed to convert into body.");
self.body = Some(body);
self
}
pub fn set_body_json<B: Serialize>(mut self, body: B) -> Self {
let body = serde_json::to_vec(&body).expect("Failed to convert into body.");
self.body = Some(body);
self.mime = "application/json".to_string();
self
}
pub fn set_body_string<T>(mut self, body: T) -> Self
where
T: TryInto<String>,
<T as TryInto<String>>::Error: std::fmt::Debug,
{
let body = body.try_into().expect("Failed to convert into body.");
self.body = Some(body.into_bytes());
self.mime = "text/plain".to_string();
self
}
pub fn set_body_raw<B>(mut self, body: B, mime: &str) -> Self
where
B: TryInto<Vec<u8>>,
<B as TryInto<Vec<u8>>>::Error: std::fmt::Debug,
{
let body = body.try_into().expect("Failed to convert into body.");
self.body = Some(body);
self.mime = mime.to_string();
self
}
pub fn set_delay(mut self, delay: Duration) -> Self {
self.delay = Some(delay);
self
}
pub(crate) fn generate_response(&self) -> Response<Full<Bytes>> {
let mut response = Response::builder().status(self.status_code);
let mut headers = self.headers.clone();
if !self.mime.is_empty() {
headers.insert(http::header::CONTENT_TYPE, self.mime.parse().unwrap());
}
*response.headers_mut().unwrap() = headers;
let body = self.body.clone().unwrap_or_default();
response.body(body.into()).unwrap()
}
pub(crate) fn delay(&self) -> &Option<Duration> {
&self.delay
}
}