use crate::assert::Assert;
use hyper::{
body::Body,
client::HttpConnector,
header::{HeaderMap, HeaderName, HeaderValue},
http::request::Request as HyperRequest,
Client, Method, Uri,
};
use serde_json::Value;
const METHODS_NO_BODY: &[Method] = &[
Method::CONNECT,
Method::HEAD,
Method::GET,
Method::OPTIONS,
Method::TRACE,
];
pub trait RequestHeaders {
fn to_header_map(&self) -> HeaderMap;
}
impl RequestHeaders for Vec<(HeaderName, HeaderValue)> {
fn to_header_map(&self) -> HeaderMap {
let mut map = HeaderMap::new();
for (key, value) in self {
map.append(key, value.clone());
}
map
}
}
impl RequestHeaders for HeaderMap {
fn to_header_map(&self) -> HeaderMap {
self.clone()
}
}
pub struct Request<'c> {
pub method: Method,
pub uri: Uri,
pub headers: HeaderMap,
pub payload: Option<Body>,
pub client: &'c Client<HttpConnector>,
}
impl Request<'_> {
pub fn headers<H: RequestHeaders>(mut self, headers: H) -> Self {
self.headers = headers.to_header_map();
self
}
pub fn payload(mut self, json: Value) -> Self {
if METHODS_NO_BODY.contains(&self.method) {
println!(
"{} does not support HTTP body. No payload will be sent.",
self.method
);
return self;
}
self.payload = Some(Body::from(json.to_string()));
self
}
pub async fn assert(self) -> Assert {
let mut req = HyperRequest::new(self.payload.unwrap_or_else(Body::empty));
*req.method_mut() = self.method;
*req.headers_mut() = self.headers;
*req.uri_mut() = self.uri;
let response = self.client.request(req).await.expect("valid response");
Assert::new(response).await
}
}