use http_types::headers::{HeaderName, HeaderValue};
use http_types::{Response, StatusCode};
use serde::Serialize;
use std::collections::HashMap;
use std::convert::TryInto;
use std::str::FromStr;
use std::time::Duration;
#[derive(Clone, Debug)]
pub struct ResponseTemplate {
mime: Option<http_types::Mime>,
status_code: StatusCode,
headers: HashMap<HeaderName, Vec<HeaderValue>>,
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: HashMap::new(),
mime: None,
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.");
match self.headers.get_mut(&key) {
Some(headers) => {
headers.push(value);
}
None => {
self.headers.insert(key, vec![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, vec![value]);
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 = Some(
http_types::Mime::from_str("application/json")
.expect("Failed to convert into Mime header"),
);
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 = Some(
http_types::Mime::from_str("text/plain").expect("Failed to convert into Mime header"),
);
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 =
Some(http_types::Mime::from_str(mime).expect("Failed to convert into Mime header"));
self
}
pub fn set_delay(mut self, delay: Duration) -> Self {
self.delay = Some(delay);
self
}
pub(crate) fn generate_response(&self) -> Response {
let mut response = Response::new(self.status_code);
for (header_name, header_values) in &self.headers {
response.insert_header(header_name.clone(), header_values.as_slice());
}
if let Some(body) = &self.body {
response.set_body(body.clone());
}
if let Some(mime) = &self.mime {
response.set_content_type(mime.to_owned());
}
response
}
pub(crate) fn delay(&self) -> &Option<Duration> {
&self.delay
}
}