use crate::config::advanced::callout::CachePolicy;
use crate::error::{Error, Result};
use crate::http::{HttpClientOptions, load_reqwest_certs, load_reqwest_identity};
use reqwest::{Certificate, Identity};
use serde::Deserialize;
#[derive(Deserialize, Debug, Clone)]
#[serde(try_from = "HttpClientOptions", deny_unknown_fields)]
pub struct HttpClientConfig {
cert: Option<Vec<Certificate>>,
identity: Option<Identity>,
use_cache: bool,
user_agent: Option<String>,
cache: CachePolicy,
}
impl Default for HttpClientConfig {
fn default() -> Self {
Self {
cert: None,
identity: None,
use_cache: true,
user_agent: None,
cache: CachePolicy::default(),
}
}
}
impl HttpClientConfig {
pub fn new(cert: Option<Vec<Certificate>>, identity: Option<Identity>, use_cache: bool) -> Self {
Self {
cert,
identity,
use_cache,
cache: CachePolicy::default(),
..Default::default()
}
}
pub fn new_with_cache(
cert: Option<Vec<Certificate>>,
identity: Option<Identity>,
use_cache: bool,
cache: CachePolicy,
) -> Self {
Self {
cert,
identity,
use_cache,
cache,
..Default::default()
}
}
pub fn into_inner(
self,
) -> (
Option<Vec<Certificate>>,
Option<Identity>,
bool,
Option<String>,
CachePolicy,
) {
(
self.cert,
self.identity,
self.use_cache,
self.user_agent,
self.cache,
)
}
pub fn with_user_agent(mut self, user_agent: String) -> Self {
self.user_agent = Some(user_agent);
self
}
}
impl TryFrom<HttpClientOptions> for HttpClientConfig {
type Error = Error;
fn try_from(root_store_pair: HttpClientOptions) -> Result<Self> {
let (key_pair, root_store, use_cache, cache) = root_store_pair.into_inner();
let cert = root_store.map(load_reqwest_certs).transpose()?;
let identity = key_pair.as_ref().map(load_reqwest_identity).transpose()?;
Ok(Self::new_with_cache(cert, identity, use_cache, cache))
}
}
#[cfg(test)]
pub(crate) mod tests {
use crate::http::tests::with_test_certificates;
use crate::http::{CertificateKeyPairPath, HttpClientOptions};
use std::path::Path;
use super::*;
#[tokio::test]
async fn test_tls_client_config() {
with_test_certificates(|path, _, _| {
let client_config = client_config_from_path(path);
let (certs, identity, _, _, _) = client_config.into_inner();
assert_eq!(certs.unwrap().len(), 1);
assert!(identity.is_some());
});
}
pub(crate) fn client_config_from_path(path: &Path) -> HttpClientConfig {
HttpClientConfig::try_from(HttpClientOptions::new(
Some(CertificateKeyPairPath::new(
path.join("cert.pem"),
path.join("key.pem"),
)),
Some(path.join("cert.pem")),
true,
))
.unwrap()
}
}