use crate::courierust_body::Body;
use crate::courierust_client::Client;
use crate::courierust_error::Result;
use crate::courierust_h2::priority::Priority;
use crate::courierust_http::form;
use crate::courierust_http::header::{HeaderMap, HeaderName, HeaderValue};
use crate::courierust_http::method::Method;
use crate::courierust_http::request::Request;
use crate::courierust_http::response::Response;
use std::time::Duration;
pub struct RequestBuilder<'a> {
client: &'a Client,
url: String,
req: Request<Body>,
priority: Priority,
timeout: Option<Duration>,
}
impl<'a> RequestBuilder<'a> {
pub(crate) fn new(client: &'a Client, url: String, method: Method) -> Self {
Self {
client,
url,
req: Request::new(method, "/"),
priority: Priority::default(),
timeout: None,
}
}
pub fn header(mut self, name: impl Into<HeaderName>, value: impl Into<HeaderValue>) -> Self {
self.req.headers.insert(name.into(), value.into());
self
}
pub fn append_header(
mut self,
name: impl Into<HeaderName>,
value: impl Into<HeaderValue>,
) -> Self {
self.req.headers.append(name.into(), value.into());
self
}
pub fn headers(mut self, headers: HeaderMap) -> Self {
for (name, value) in headers.into_vec() {
self.req.headers.insert(name, value);
}
self
}
pub fn body(mut self, body: impl Into<Body>) -> Self {
self.req.body = body.into();
self
}
pub fn query<'p, I>(mut self, params: I) -> Self
where
I: IntoIterator<Item = (&'p str, &'p str)>,
{
let encoded = form::serialize(params);
if !encoded.is_empty() {
let at = self.url.find('#').unwrap_or(self.url.len());
let separator = if self.url[..at].contains('?') {
'&'
} else {
'?'
};
self.url.insert(at, separator);
self.url.insert_str(at + 1, &encoded);
}
self
}
pub fn form<'p, I>(mut self, fields: I) -> Self
where
I: IntoIterator<Item = (&'p str, &'p str)>,
{
let encoded = form::serialize(fields);
if !self.req.headers.contains_key("content-type") {
self.req.headers.insert(
HeaderName::from_static("content-type"),
HeaderValue::from_static("application/x-www-form-urlencoded"),
);
}
self.req.body = Body::from(encoded);
self
}
pub fn basic_auth(self, username: &str, password: &str) -> Self {
let mut credentials = String::with_capacity(username.len() + password.len() + 1);
credentials.push_str(username);
credentials.push(':');
credentials.push_str(password);
let mut value = String::with_capacity(
6 + crate::courierust_crypto::base64::encoded_len(credentials.len()),
);
value.push_str("Basic ");
crate::courierust_crypto::base64::encode_into(credentials.as_bytes(), &mut value);
self.header(
HeaderName::from_static("authorization"),
HeaderValue::from(value),
)
}
pub fn bearer_auth(self, token: &str) -> Self {
let mut value = String::with_capacity(7 + token.len());
value.push_str("Bearer ");
value.push_str(token);
self.header(
HeaderName::from_static("authorization"),
HeaderValue::from(value),
)
}
pub fn priority(mut self, priority: Priority) -> Self {
self.priority = priority;
self
}
pub fn timeout(mut self, timeout: Duration) -> Self {
self.timeout = Some(timeout);
self
}
pub fn send(self) -> Result<Response<Body>> {
self.client
.execute_built(&self.url, self.req, self.priority, self.timeout)
}
}