use std::time::Duration;
use flawless::idempotent::Idempotence;
use crate::transport::flawless::{Flawless, Idempotent};
use crate::{response::Response, transport::HTTPTransport, Config, Error, IntoBody};
#[derive(Debug, Clone)]
pub struct Request<T>
where
T: HTTPTransport,
{
config: Config,
transport: T,
method: String,
url: String,
headers: Vec<(String, String)>,
body: Vec<u8>,
}
impl<T: HTTPTransport> Request<T> {
pub fn new<M, U>(transport: T, method: M, url: U) -> Request<T>
where
M: Into<String>,
U: Into<String>,
{
Request {
config: Config::default(),
transport,
method: method.into(),
url: url.into(),
headers: Vec::new(),
body: Vec::new(),
}
}
pub fn send(self) -> Result<Response, Error> {
self.transport.send(self.config, self.method, self.url, self.headers, self.body)
}
pub fn timeout(mut self, duration: Duration) -> Self {
self.config.set_timeout(duration);
self
}
pub fn response_body_limit(mut self, limit: u64) -> Self {
self.config.set_response_body_limit(limit);
self
}
pub fn header<N: AsRef<str>>(&self, name: N) -> Option<&String> {
let name_l = name.as_ref().to_lowercase();
for header in self.headers.iter() {
let header_name_l = header.0.to_lowercase();
if name_l == header_name_l {
return Some(&header.1);
}
}
None
}
pub fn set_header<N, V>(mut self, name: N, value: V) -> Self
where
N: Into<String>,
V: Into<String>,
{
let name: String = name.into();
for header in self.headers.iter_mut() {
if header.0.to_lowercase() == name.to_lowercase() {
header.1 = value.into();
return self;
}
}
self.headers.push((name, value.into()));
self
}
pub fn body<B: IntoBody<T>>(self, body: B) -> Self {
let (mut request, body) = body.into(self);
request.body = body;
request
}
}
impl Idempotence for Request<Flawless> {
type Idempotent = Request<Idempotent>;
fn idempotent(self) -> Self::Idempotent {
let mut config = self.config;
config.set_idempotent(true);
Request {
config,
transport: Idempotent,
method: self.method,
url: self.url,
headers: self.headers,
body: self.body,
}
}
}
pub fn get<U: Into<String>>(url: U) -> Request<Flawless> {
Request::new(Flawless, "GET", url)
}
pub fn post<U: Into<String>>(url: U) -> Request<Flawless> {
Request::new(Flawless, "POST", url)
}
pub fn delete<U: Into<String>>(url: U) -> Request<Flawless> {
Request::new(Flawless, "DELETE", url)
}
pub fn put<U: Into<String>>(url: U) -> Request<Flawless> {
Request::new(Flawless, "PUT", url)
}
pub fn head<U: Into<String>>(url: U) -> Request<Flawless> {
Request::new(Flawless, "HEAD", url)
}
pub fn patch<U: Into<String>>(url: U) -> Request<Flawless> {
Request::new(Flawless, "PATCH", url)
}