use std::time::Duration;
use qubit_config::{ConfigReader, ConfigResult};
use super::HttpConfigError;
use crate::constants::{
DEFAULT_CONNECT_TIMEOUT_SECS, DEFAULT_READ_TIMEOUT_SECS, DEFAULT_WRITE_TIMEOUT_SECS,
};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct HttpTimeoutOptions {
pub connect_timeout: Duration,
pub read_timeout: Duration,
pub write_timeout: Duration,
pub request_timeout: Option<Duration>,
}
impl Default for HttpTimeoutOptions {
fn default() -> Self {
Self {
connect_timeout: Duration::from_secs(DEFAULT_CONNECT_TIMEOUT_SECS),
read_timeout: Duration::from_secs(DEFAULT_READ_TIMEOUT_SECS),
write_timeout: Duration::from_secs(DEFAULT_WRITE_TIMEOUT_SECS),
request_timeout: None,
}
}
}
struct TimeoutConfigInput {
connect_timeout: Option<Duration>,
read_timeout: Option<Duration>,
write_timeout: Option<Duration>,
request_timeout: Option<Duration>,
}
fn read_timeout_config<R>(config: &R) -> ConfigResult<TimeoutConfigInput>
where
R: ConfigReader + ?Sized,
{
Ok(TimeoutConfigInput {
connect_timeout: config.get_optional("connect_timeout")?,
read_timeout: config.get_optional("read_timeout")?,
write_timeout: config.get_optional("write_timeout")?,
request_timeout: config.get_optional("request_timeout")?,
})
}
impl HttpTimeoutOptions {
pub fn validate(&self) -> Result<(), HttpConfigError> {
validate_positive_duration("connect_timeout", self.connect_timeout)?;
validate_positive_duration("read_timeout", self.read_timeout)?;
validate_positive_duration("write_timeout", self.write_timeout)?;
if let Some(request_timeout) = self.request_timeout {
validate_positive_duration("request_timeout", request_timeout)?;
}
Ok(())
}
pub fn from_config<R>(config: &R) -> Result<Self, HttpConfigError>
where
R: ConfigReader + ?Sized,
{
let raw = read_timeout_config(config).map_err(HttpConfigError::from)?;
let mut opts = HttpTimeoutOptions::default();
if let Some(d) = raw.connect_timeout {
opts.connect_timeout = d;
}
if let Some(d) = raw.read_timeout {
opts.read_timeout = d;
}
if let Some(d) = raw.write_timeout {
opts.write_timeout = d;
}
opts.request_timeout = raw.request_timeout;
opts.validate()?;
Ok(opts)
}
}
fn validate_positive_duration(path: &str, value: Duration) -> Result<(), HttpConfigError> {
if value.is_zero() {
return Err(HttpConfigError::invalid_value(
path,
"Timeout value must be greater than 0",
));
}
Ok(())
}