use crate::utils::network::tls_config::get_client_config;
use hyper::client::{HttpConnector, ResponseFuture};
use hyper::{Body, Client};
#[cfg(feature = "proxy")]
use hyper_proxy::{Proxy, ProxyConnector};
use hyper_rustls::HttpsConnector;
#[cfg(feature = "proxy")]
use tokio::io;
#[derive(Debug)]
pub enum HttpClientError {
TlsConfigError(rustls::Error),
#[cfg(feature = "proxy")]
ProxyError(io::Error),
}
pub trait HttpClient
where
Self: Clone + Send + Sync + 'static,
{
fn request(&self, request: hyper::Request<Body>) -> ResponseFuture;
}
#[cfg(feature = "proxy")]
pub struct ProxyHttpClient {
client: Client<ProxyConnector<HttpsConnector<HttpConnector>>>,
}
#[cfg(feature = "proxy")]
impl ProxyHttpClient {
pub fn new(proxy: Proxy) -> Result<ProxyHttpClient, HttpClientError> {
let config = get_client_config().map_err(HttpClientError::TlsConfigError)?;
let https = hyper_rustls::HttpsConnectorBuilder::new()
.with_tls_config(config)
.https_or_http()
.enable_http1()
.enable_http2()
.build();
let proxy_connector =
ProxyConnector::from_proxy(https, proxy).map_err(HttpClientError::ProxyError)?;
let client = hyper::Client::builder().build::<_, Body>(proxy_connector);
Ok(Self { client })
}
}
#[cfg(feature = "proxy")]
impl HttpClient for ProxyHttpClient {
fn request(&self, request: hyper::Request<Body>) -> ResponseFuture {
self.client.request(request)
}
}
#[cfg(feature = "proxy")]
impl Clone for ProxyHttpClient {
fn clone(&self) -> Self {
Self {
client: self.client.clone(),
}
}
}
pub struct SimpleHttpClient {
client: Client<HttpsConnector<HttpConnector>>,
}
impl SimpleHttpClient {
pub fn new() -> Result<SimpleHttpClient, HttpClientError> {
let config = get_client_config().map_err(HttpClientError::TlsConfigError)?;
let https = hyper_rustls::HttpsConnectorBuilder::new()
.with_tls_config(config)
.https_only()
.enable_http1()
.enable_http2()
.build();
let client = hyper::Client::builder().build::<_, Body>(https);
Ok(Self { client })
}
}
impl HttpClient for SimpleHttpClient {
fn request(&self, request: hyper::Request<Body>) -> ResponseFuture {
self.client.request(request)
}
}
impl Clone for SimpleHttpClient {
fn clone(&self) -> Self {
Self {
client: self.client.clone(),
}
}
}