use std::time::Duration;
use reqwest::Client;
use serde::{Deserialize, Serialize};
use crate::constants::{http, limits};
use crate::errors::{AuthError, AuthResult};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ClientConfig {
pub http2: bool,
pub tcp_keepalive: Option<Duration>,
pub tcp_nodelay: bool,
pub pool_idle_timeout: Option<Duration>,
pub pool_max_per_host: usize,
pub request_timeout: Duration,
pub connect_timeout: Duration,
pub rate_limit_rps: u32,
}
impl Default for ClientConfig {
fn default() -> Self {
Self {
http2: false, tcp_keepalive: Some(Duration::from_secs(30)),
tcp_nodelay: true,
pool_idle_timeout: Some(http::POOL_IDLE_TIMEOUT),
pool_max_per_host: http::POOL_MAX_PER_HOST,
request_timeout: http::DEFAULT_TIMEOUT,
connect_timeout: http::CONNECT_TIMEOUT,
rate_limit_rps: limits::DEFAULT_RATE_LIMIT_RPS,
}
}
}
impl ClientConfig {
pub fn build_http_client(&self) -> AuthResult<Client> {
let mut client_builder = Client::builder()
.cookie_store(true) .timeout(self.request_timeout)
.connect_timeout(self.connect_timeout)
.user_agent(http::USER_AGENT)
.http2_keep_alive_interval(Some(http::HTTP2_KEEP_ALIVE_INTERVAL))
.http2_keep_alive_timeout(http::HTTP2_KEEP_ALIVE_TIMEOUT)
.tcp_nodelay(self.tcp_nodelay)
.pool_max_idle_per_host(self.pool_max_per_host);
if self.http2 {
client_builder = client_builder.http2_adaptive_window(true);
}
if let Some(keepalive) = self.tcp_keepalive {
client_builder = client_builder.tcp_keepalive(keepalive);
}
if let Some(idle_timeout) = self.pool_idle_timeout {
client_builder = client_builder.pool_idle_timeout(idle_timeout);
}
client_builder.build().map_err(AuthError::Http)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_client_config_default() {
let config = ClientConfig::default();
assert!(!config.http2); assert!(config.tcp_nodelay);
assert_eq!(config.rate_limit_rps, limits::DEFAULT_RATE_LIMIT_RPS);
}
#[test]
fn test_client_config_custom() {
let config = ClientConfig {
http2: true,
rate_limit_rps: 10,
..Default::default()
};
assert!(config.http2);
assert_eq!(config.rate_limit_rps, 10);
assert!(config.tcp_nodelay); }
#[test]
fn test_http_client_creation() {
let config = ClientConfig::default();
let result = config.build_http_client();
assert!(result.is_ok());
}
#[test]
fn test_http_client_with_custom_config() {
let config = ClientConfig {
request_timeout: Duration::from_secs(30),
connect_timeout: Duration::from_secs(10),
..Default::default()
};
let result = config.build_http_client();
assert!(result.is_ok());
}
}