use super::{interface::InterfaceString, setopt::*, *};
#[doc(hidden)]
pub trait WithRequestConfig: Sized {
fn with_config(self, f: impl FnOnce(&mut RequestConfig)) -> Self;
}
macro_rules! define_request_config {
($(
$(#[$meta:meta])*
$field:ident: $t:ty,
)*) => {
#[derive(Clone, Debug, Default)]
pub struct RequestConfig {
$(
$(#[$meta])*
pub(crate) $field: $t,
)*
}
impl RequestConfig {
pub(crate) fn merge(&mut self, defaults: &Self) {
$(
$(#[$meta])*
{
if self.$field.is_none() {
if let Some(value) = defaults.$field.as_ref() {
self.$field = Some(value.clone());
}
}
}
)*
}
}
};
}
define_request_config! {
timeout: Option<Duration>,
connect_timeout: Option<Duration>,
low_speed_timeout: Option<(u32, Duration)>,
version_negotiation: Option<VersionNegotiation>,
automatic_decompression: Option<bool>,
expect_continue: Option<ExpectContinue>,
authentication: Option<Authentication>,
credentials: Option<Credentials>,
tcp_keepalive: Option<Duration>,
tcp_nodelay: Option<bool>,
interface: Option<InterfaceString>,
ip_version: Option<IpVersion>,
dial: Option<Dialer>,
proxy: Option<Option<http::Uri>>,
proxy_blacklist: Option<proxy::Blacklist>,
proxy_authentication: Option<Authentication>,
proxy_credentials: Option<Credentials>,
max_upload_speed: Option<u64>,
max_download_speed: Option<u64>,
enable_metrics: Option<bool>,
#[cfg(feature = "tls")]
tls_config: Option<crate::tls::TlsConfig>,
#[cfg(feature = "tls")]
proxy_tls_config: Option<crate::tls::TlsConfig>,
redirect_policy: Option<RedirectPolicy>,
auto_referer: Option<bool>,
title_case_headers: Option<bool>,
}
impl RequestConfig {
pub(crate) fn client_defaults() -> Self {
Self {
version_negotiation: Some(VersionNegotiation::default()),
automatic_decompression: Some(true),
authentication: Some(Authentication::default()),
#[cfg(feature = "tls")]
tls_config: Some(crate::tls::TlsConfig::default()),
..Default::default()
}
}
}
impl SetOpt for RequestConfig {
fn set_opt(&self, easy: &mut EasyHandle) -> Result<(), SetOptError> {
if let Some(timeout) = self.timeout {
easy.timeout(timeout)?;
}
if let Some((low_speed, timeout)) = self.low_speed_timeout {
easy.low_speed_limit(low_speed)?;
easy.low_speed_time(timeout)?;
}
if let Some(timeout) = self.connect_timeout {
easy.connect_timeout(timeout)?;
}
if let Some(negotiation) = self.version_negotiation.as_ref() {
negotiation.set_opt(easy)?;
}
{
if let Some(enable) = self.automatic_decompression {
if enable {
easy.accept_encoding("")?;
} else {
unsafe {
match curl_sys::curl_easy_setopt(
easy.raw(),
curl_sys::CURLOPT_ACCEPT_ENCODING,
0,
) {
curl_sys::CURLE_OK => {}
code => return Err(curl::Error::new(code).into()),
}
}
}
}
}
if let Some(expect_continue) = self.expect_continue.as_ref() {
expect_continue.set_opt(easy)?;
}
if let Some(auth) = self.authentication.as_ref() {
auth.set_opt(easy)?;
}
if let Some(credentials) = self.credentials.as_ref() {
credentials.set_opt(easy)?;
}
if let Some(interval) = self.tcp_keepalive {
easy.tcp_keepalive(true)?;
easy.tcp_keepintvl(interval)?;
}
if let Some(enable) = self.tcp_nodelay {
easy.tcp_nodelay(enable)?;
}
if let Some(interface) = self.interface.as_ref() {
interface.set_opt(easy)?;
}
if let Some(version) = self.ip_version.as_ref() {
version.set_opt(easy)?;
}
if let Some(dialer) = self.dial.as_ref() {
dialer.set_opt(easy)?;
}
if let Some(proxy) = self.proxy.as_ref() {
match proxy {
Some(uri) => easy.proxy(&format!("{}", uri))?,
None => easy.proxy("")?,
}
}
if let Some(blacklist) = self.proxy_blacklist.as_ref() {
blacklist.set_opt(easy)?;
}
if let Some(auth) = self.proxy_authentication.as_ref() {
auth.set_opt_proxy(easy)?;
}
if let Some(credentials) = self.proxy_credentials.as_ref() {
credentials.set_opt_proxy(easy)?;
}
if let Some(max) = self.max_upload_speed {
easy.max_send_speed(max)?;
}
if let Some(max) = self.max_download_speed {
easy.max_recv_speed(max)?;
}
#[cfg(feature = "tls")]
if let Some(config) = self.tls_config.as_ref() {
config.set_opt(easy)?;
}
#[cfg(feature = "tls")]
if let Some(config) = self.proxy_tls_config.as_ref() {
config.set_opt_proxy(easy)?;
}
if let Some(enable) = self.enable_metrics {
easy.progress(enable)?;
}
Ok(())
}
}