arangors_graph_exporter/client/
builder.rs

1use crate::DatabaseConfiguration;
2use crate::client::config::ClientConfig;
3use reqwest::{Certificate, Client};
4use reqwest_middleware::{ClientBuilder, ClientWithMiddleware};
5use reqwest_retry::RetryTransientMiddleware;
6use reqwest_retry::policies::ExponentialBackoff;
7use std::fs::File;
8use std::io::Read;
9
10pub fn make_url(db_config: &DatabaseConfiguration, path: &str) -> String {
11    db_config.endpoints[0].clone() + "/_db/" + &db_config.database + path
12}
13
14pub fn build_client(
15    config: &ClientConfig,
16) -> Result<reqwest_middleware::ClientWithMiddleware, String> {
17    let mut client_builder = reqwest::Client::builder();
18    client_builder = if config.use_tls {
19        client_builder = client_builder
20            .min_tls_version(reqwest::tls::Version::TLS_1_2)
21            .https_only(true);
22
23        if let Some(cert_path) = &config.tls_cert {
24            let cert = get_cert(cert_path)?;
25            client_builder.add_root_certificate(cert).use_rustls_tls()
26        } else {
27            client_builder
28                .danger_accept_invalid_certs(true)
29                .use_rustls_tls()
30        }
31    } else {
32        client_builder.danger_accept_invalid_certs(true)
33    };
34    let client = client_builder
35        .build()
36        .map_err(|err| format!("Error message from request builder: {:?}", err))?;
37    let client = client_with_retries(&config.n_retries, client);
38    Ok(client)
39}
40
41fn get_cert(cert_path: &String) -> Result<Certificate, String> {
42    if cert_path.is_empty() {
43        return Err(
44            "Error message from reading TLS certificate: Certificate path is empty".to_string(),
45        );
46    }
47    let mut cert_buf = vec![];
48    let mut file = File::open(cert_path)
49        .map_err(|err| format!("Error message from reading TLS certificate: {:?}", err))?;
50    file.read_to_end(&mut cert_buf)
51        .map_err(|err| format!("Error message from reading TLS certificate: {:?}", err))?;
52    let cert = reqwest::Certificate::from_pem(&cert_buf)
53        .map_err(|err| format!("Error message from request builder: {:?}", err))?;
54    Ok(cert)
55}
56
57fn client_with_retries(n_retries: &u32, client: Client) -> ClientWithMiddleware {
58    let retry_policy = ExponentialBackoff::builder()
59        .retry_bounds(
60            std::time::Duration::from_millis(30),
61            std::time::Duration::from_millis(3000),
62        )
63        .build_with_max_retries(*n_retries);
64    let retry_middleware = RetryTransientMiddleware::new_with_policy(retry_policy);
65    ClientBuilder::new(client).with(retry_middleware).build()
66}