mirror of
https://github.com/kodjodevf/mangayomi.git
synced 2026-01-11 22:40:36 +00:00
165 lines
5.1 KiB
Rust
165 lines
5.1 KiB
Rust
use crate::api::rhttp::error::RhttpError;
|
|
use chrono::Duration;
|
|
use reqwest::{tls, Certificate};
|
|
pub use tokio_util::sync::CancellationToken;
|
|
|
|
pub struct ClientSettings {
|
|
pub timeout: Option<Duration>,
|
|
pub connect_timeout: Option<Duration>,
|
|
pub throw_on_status_code: bool,
|
|
pub proxy_settings: Option<ProxySettings>,
|
|
pub redirect_settings: Option<RedirectSettings>,
|
|
pub tls_settings: Option<TlsSettings>,
|
|
}
|
|
|
|
pub enum ProxySettings {
|
|
NoProxy,
|
|
}
|
|
|
|
pub enum RedirectSettings {
|
|
NoRedirect,
|
|
LimitedRedirects(i32),
|
|
}
|
|
|
|
pub struct TlsSettings {
|
|
pub trust_root_certificates: bool,
|
|
pub trusted_root_certificates: Vec<Vec<u8>>,
|
|
pub verify_certificates: bool,
|
|
pub client_certificate: Option<ClientCertificate>,
|
|
pub min_tls_version: Option<TlsVersion>,
|
|
pub max_tls_version: Option<TlsVersion>,
|
|
}
|
|
|
|
pub struct ClientCertificate {
|
|
pub certificate: Vec<u8>,
|
|
pub private_key: Vec<u8>,
|
|
}
|
|
|
|
pub enum TlsVersion {
|
|
Tls1_2,
|
|
Tls1_3,
|
|
}
|
|
|
|
impl Default for ClientSettings {
|
|
fn default() -> Self {
|
|
ClientSettings {
|
|
timeout: None,
|
|
connect_timeout: None,
|
|
throw_on_status_code: true,
|
|
proxy_settings: None,
|
|
redirect_settings: None,
|
|
tls_settings: None,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
pub struct RequestClient {
|
|
pub(crate) client: reqwest::Client,
|
|
pub(crate) throw_on_status_code: bool,
|
|
|
|
/// A token that can be used to cancel all requests made by this client.
|
|
pub(crate) cancel_token: CancellationToken,
|
|
}
|
|
|
|
impl RequestClient {
|
|
pub(crate) fn new_default() -> Self {
|
|
create_client(ClientSettings::default()).unwrap()
|
|
}
|
|
|
|
pub(crate) fn new(settings: ClientSettings) -> Result<RequestClient, RhttpError> {
|
|
create_client(settings)
|
|
}
|
|
}
|
|
|
|
fn create_client(settings: ClientSettings) -> Result<RequestClient, RhttpError> {
|
|
let client: reqwest::Client = {
|
|
let mut client = reqwest::Client::builder();
|
|
if let Some(proxy_settings) = settings.proxy_settings {
|
|
match proxy_settings {
|
|
ProxySettings::NoProxy => client = client.no_proxy(),
|
|
}
|
|
}
|
|
|
|
if let Some(redirect_settings) = settings.redirect_settings {
|
|
client = match redirect_settings {
|
|
RedirectSettings::NoRedirect => client.redirect(reqwest::redirect::Policy::none()),
|
|
RedirectSettings::LimitedRedirects(max_redirects) => {
|
|
client.redirect(reqwest::redirect::Policy::limited(max_redirects as usize))
|
|
}
|
|
};
|
|
}
|
|
|
|
if let Some(timeout) = settings.timeout {
|
|
client = client.timeout(
|
|
timeout
|
|
.to_std()
|
|
.map_err(|e| RhttpError::RhttpUnknownError(e.to_string()))?,
|
|
);
|
|
}
|
|
if let Some(timeout) = settings.connect_timeout {
|
|
client = client.connect_timeout(
|
|
timeout
|
|
.to_std()
|
|
.map_err(|e| RhttpError::RhttpUnknownError(e.to_string()))?,
|
|
);
|
|
}
|
|
|
|
if let Some(tls_settings) = settings.tls_settings {
|
|
if !tls_settings.trust_root_certificates {
|
|
client = client.tls_built_in_root_certs(false);
|
|
}
|
|
|
|
for cert in tls_settings.trusted_root_certificates {
|
|
client =
|
|
client.add_root_certificate(Certificate::from_pem(&cert).map_err(|e| {
|
|
RhttpError::RhttpUnknownError(format!(
|
|
"Error adding trusted certificate: {e:?}"
|
|
))
|
|
})?);
|
|
}
|
|
|
|
if !tls_settings.verify_certificates {
|
|
client = client.danger_accept_invalid_certs(true);
|
|
}
|
|
|
|
if let Some(client_certificate) = tls_settings.client_certificate {
|
|
let identity = &[
|
|
client_certificate.certificate.as_slice(),
|
|
"\n".as_bytes(),
|
|
client_certificate.private_key.as_slice(),
|
|
]
|
|
.concat();
|
|
|
|
client = client.identity(
|
|
reqwest::Identity::from_pem(identity)
|
|
.map_err(|e| RhttpError::RhttpUnknownError(format!("{e:?}")))?,
|
|
);
|
|
}
|
|
|
|
if let Some(min_tls_version) = tls_settings.min_tls_version {
|
|
client = client.min_tls_version(match min_tls_version {
|
|
TlsVersion::Tls1_2 => tls::Version::TLS_1_2,
|
|
TlsVersion::Tls1_3 => tls::Version::TLS_1_3,
|
|
});
|
|
}
|
|
|
|
if let Some(max_tls_version) = tls_settings.max_tls_version {
|
|
client = client.max_tls_version(match max_tls_version {
|
|
TlsVersion::Tls1_2 => tls::Version::TLS_1_2,
|
|
TlsVersion::Tls1_3 => tls::Version::TLS_1_3,
|
|
});
|
|
}
|
|
}
|
|
|
|
client
|
|
.build()
|
|
.map_err(|e| RhttpError::RhttpUnknownError(format!("{e:?}")))?
|
|
};
|
|
|
|
Ok(RequestClient {
|
|
client,
|
|
throw_on_status_code: settings.throw_on_status_code,
|
|
cancel_token: CancellationToken::new(),
|
|
})
|
|
}
|