use crate::common::types::Body;
use derive_builder::Builder;
use http::{
HeaderMap, HeaderValue,
header::{IntoHeaderName, USER_AGENT},
};
use std::time::Duration;
#[derive(Debug, Clone, Builder)]
#[builder(name = "HttpConfigBuilder", pattern = "owned", setter(strip_option))]
pub struct HttpConfig {
#[builder(default = Duration::from_secs(300))]
timeout: Duration,
#[builder(default = Duration::from_secs(10))]
connect_timeout: Duration,
#[builder(default = None)]
proxy: Option<String>,
#[builder(default = HeaderMap::new())]
headers: HeaderMap,
#[builder(default = Body::new())]
bodys: Body,
}
impl HttpConfig {
pub fn builder() -> HttpConfigBuilder {
HttpConfigBuilder::default()
}
#[inline]
pub fn timeout(&self) -> Duration {
self.timeout
}
#[inline]
pub fn connect_timeout(&self) -> Duration {
self.connect_timeout
}
#[inline]
pub fn proxy(&self) -> Option<&String> {
self.proxy.as_ref()
}
#[inline]
pub fn user_agent(&self) -> Option<&HeaderValue> {
self.headers.get(USER_AGENT)
}
#[inline]
pub fn headers(&self) -> &HeaderMap {
&self.headers
}
#[inline]
pub fn bodys(&self) -> &Body {
&self.bodys
}
#[inline]
pub fn get_body(&self, key: &str) -> Option<&serde_json::Value> {
self.bodys.get(key)
}
#[inline]
pub fn get_header(&self, key: &str) -> Option<&HeaderValue> {
self.headers.get(key)
}
pub fn add_header<K: IntoHeaderName>(&mut self, key: K, value: HeaderValue) -> &mut Self {
self.headers.insert(key, value);
self
}
pub fn remove_header(&mut self, key: &str) -> Option<HeaderValue> {
self.headers.remove(key)
}
pub fn add_body(
&mut self,
key: impl Into<String>,
value: impl Into<serde_json::Value>,
) -> &mut Self {
self.bodys.insert(key.into(), value.into());
self
}
pub fn remove_body(&mut self, key: &str) -> Option<serde_json::Value> {
self.bodys.remove(key)
}
pub fn with_timeout(&mut self, timeout: Duration) -> &mut Self {
self.timeout = timeout;
self
}
pub fn with_connect_timeout(&mut self, connect_timeout: Duration) -> &mut Self {
self.connect_timeout = connect_timeout;
self
}
pub fn with_proxy(&mut self, proxy: impl Into<String>) -> &mut Self {
self.proxy = Some(proxy.into());
self
}
pub fn with_user_agent(&mut self, user_agent: HeaderValue) -> &mut Self {
self.headers.insert(USER_AGENT, user_agent);
self
}
pub fn build_reqwest_client(&self) -> reqwest::Client {
let mut client_builder = reqwest::ClientBuilder::new()
.timeout(self.timeout)
.connect_timeout(self.connect_timeout);
if let Some(ref proxy_url) = self.proxy {
if let Ok(proxy) = reqwest::Proxy::all(proxy_url) {
client_builder = client_builder.proxy(proxy);
}
}
if let Some(user_agent) = self.headers.get(USER_AGENT) {
client_builder = client_builder.user_agent(user_agent);
}
client_builder
.build()
.unwrap_or_else(|_| reqwest::Client::new())
}
}
impl Default for HttpConfig {
fn default() -> Self {
Self {
timeout: Duration::from_secs(300),
connect_timeout: Duration::from_secs(10),
proxy: None,
bodys: Body::new(),
headers: HeaderMap::new(),
}
}
}
impl HttpConfigBuilder {
pub fn header<K: IntoHeaderName>(mut self, key: K, value: HeaderValue) -> Self {
let headers_map = self.headers.get_or_insert_with(HeaderMap::new);
headers_map.insert(key, value);
self
}
pub fn body(mut self, key: impl Into<String>, value: impl Into<serde_json::Value>) -> Self {
let body_map = self.bodys.get_or_insert_with(Body::new);
body_map.insert(key.into(), value.into());
self
}
pub fn user_agent(mut self, user_agent: HeaderValue) -> Self {
self.headers
.get_or_insert_with(HeaderMap::new)
.insert(USER_AGENT, user_agent);
self
}
}