opensearch-client 0.3.1

Strongly typed OpenSearch Client
Documentation
/*
 * opensearch-client
 *
 * Rust Client for OpenSearch
 *
 * The version of the OpenAPI document: 3.1.0
 * Contact: alberto.paro@gmail.com
 * Generated by Paro OpenAPI Generator
 */

use crate::client::auth_middleware::AuthMiddleware;
use crate::client::credentials::Credentials;
use crate::Error;
use crate::{client::auth_middleware, OsClient};
#[cfg(not(target_arch = "wasm32"))]
use reqwest::{NoProxy, Proxy};
use reqwest_middleware::ClientWithMiddleware;
use reqwest_retry::{policies::ExponentialBackoff, RetryTransientMiddleware};
use std::{
    collections::HashMap,
    sync::{Arc, Mutex},
};
use url::Url;

#[derive(Clone, Debug)]
pub struct ConfigurationBuilder {
    baseurl: String,
    user_agent: Option<String>,
    retries: u32,
    credentials: HashMap<String, Credentials>,
    accept_invalid_certificates: bool,
    max_bulk_size: u32,
    #[cfg(not(target_arch = "wasm32"))]
    proxy: bool,
    #[cfg(not(target_arch = "wasm32"))]
    proxy_url: Option<Proxy>,
    #[cfg(not(target_arch = "wasm32"))]
    no_proxy_domain: Option<String>,
}

impl Default for ConfigurationBuilder {
    fn default() -> Self {
        Self {
            baseurl: "http://localhost:9200".to_owned(),
            user_agent: Some("opensearch-client/0.1.0".to_string()),
            credentials: HashMap::new(),
            accept_invalid_certificates: false,
            max_bulk_size: 200,
            #[cfg(not(target_arch = "wasm32"))]
            proxy: false,
            #[cfg(not(target_arch = "wasm32"))]
            proxy_url: None,
            #[cfg(not(target_arch = "wasm32"))]
            no_proxy_domain: None,
            #[cfg(not(test))]
            retries: 2,
            #[cfg(test)]
            retries: 0,
        }
    }
}

impl ConfigurationBuilder {
    pub fn new() -> Self {
        Default::default()
    }

    pub fn base_url(mut self, baseurl: impl Into<String>) -> Self {
        self.baseurl = baseurl.into();
        self
    }

    pub fn user_agent(mut self, user_agent: impl Into<String>) -> Self {
        self.user_agent = Some(user_agent.into());
        self
    }

    pub fn accept_invalid_certificates(mut self, accept_invalid_certificates: bool) -> Self {
        self.accept_invalid_certificates = accept_invalid_certificates;
        self
    }

    pub fn max_bulk_size(mut self, max_bulk_size: u32) -> Self {
        self.max_bulk_size = max_bulk_size;
        self
    }

    pub fn basic_auth(mut self, username: impl Into<String>, password: impl Into<String>) -> Self {
        self.credentials.insert(
            auth_middleware::nerf_dart(&Url::parse(&self.baseurl).unwrap()),
            Credentials::Basic {
                username: username.into(),
                password: Some(password.into()),
            },
        );
        self
    }

    pub fn token_auth(mut self, token: impl Into<String>) -> Self {
        self.credentials.insert(
            auth_middleware::nerf_dart(&Url::parse(&self.baseurl).unwrap()),
            Credentials::Token(token.into()),
        );
        self
    }

    pub fn legacy_auth(mut self, legacy_auth_token: impl Into<String>) -> Self {
        self.credentials.insert(
            auth_middleware::nerf_dart(&Url::parse(&self.baseurl).unwrap()),
            Credentials::EncodedBasic(legacy_auth_token.into()),
        );
        self
    }

    pub fn retries(mut self, retries: u32) -> Self {
        self.retries = retries;
        self
    }

    #[cfg(not(target_arch = "wasm32"))]
    pub fn proxy(mut self, proxy: bool) -> Self {
        self.proxy = proxy;
        self
    }

    #[cfg(not(target_arch = "wasm32"))]
    pub fn proxy_url(mut self, proxy_url: impl AsRef<str>) -> Result<Self, Error> {
        match Url::parse(proxy_url.as_ref()) {
            Ok(url_info) => {
                let username = url_info.username();
                let password = url_info.password();
                let mut proxy = Proxy::all(url_info.as_ref())?;

                if let Some(password_str) = password {
                    proxy = proxy.basic_auth(username, password_str);
                }

                proxy = proxy.no_proxy(self.get_no_proxy_domain());
                self.proxy_url = Some(proxy);
                self.proxy = true;
                Ok(self)
            }
            Err(e) => Err(Error::UrlParseError(e)),
        }
    }

    #[cfg(not(target_arch = "wasm32"))]
    pub fn no_proxy_domain(mut self, no_proxy_domain: impl AsRef<str>) -> Self {
        self.no_proxy_domain = Some(no_proxy_domain.as_ref().into());
        self
    }

    pub fn build(self) -> OsClient {
        #[cfg(target_arch = "wasm32")]
        let client_raw = {
            let mut client_core = ClientBuilder::new();
            if self.accept_invalid_certificates {
                let mut builder = client_raw.clone().builder();
                builder = builder.danger_accept_invalid_certs(true);
                builder = builder.danger_accept_invalid_hostnames(true);
                client_raw = builder.build().unwrap();
            }
            client_core.build().expect("Fail to build HTTP client.")
        };

        #[cfg(not(target_arch = "wasm32"))]
        let client_raw = {
            use reqwest::ClientBuilder;

            let mut client_core = ClientBuilder::new()
                .user_agent("opensearch-client/0.1.0")
                .pool_max_idle_per_host(20)
                .timeout(std::time::Duration::from_secs(60 * 5));

            if let Some(url) = self.proxy_url {
                client_core = client_core.proxy(url);
            }

            if !self.proxy {
                client_core = client_core.no_proxy();
            }
            if self.accept_invalid_certificates {
                client_core = client_core.danger_accept_invalid_certs(true);
                client_core = client_core.danger_accept_invalid_hostnames(true);
            }

            client_core.build().expect("Fail to build HTTP client.")
        };

        let retry_policy = ExponentialBackoff::builder()
            .retry_bounds(
                std::time::Duration::from_millis(30),
                std::time::Duration::from_millis(100),
            )
            .build_with_max_retries(self.retries);
        let retry_strategy = RetryTransientMiddleware::new_with_policy(retry_policy);
        let credentials = Arc::new(self.credentials);

        #[allow(unused_mut)]
        let mut client_builder = reqwest_middleware::ClientBuilder::new(client_raw.clone())
            .with(retry_strategy)
            .with(AuthMiddleware(credentials.clone()));

        let configuration = Configuration {
            base_path: self.baseurl.clone(),
            client: client_builder.build(),
            bulker: Arc::new(Mutex::new(String::new())),
            bulker_size: Arc::new(Mutex::new(0)),
            max_bulk_size: self.max_bulk_size,
        };
        OsClient::new(Arc::new(configuration))
    }

    #[cfg(not(target_arch = "wasm32"))]
    fn get_no_proxy_domain(&self) -> Option<NoProxy> {
        if let Some(ref no_proxy_conf) = self.no_proxy_domain {
            if !no_proxy_conf.is_empty() {
                return NoProxy::from_string(no_proxy_conf);
            }
        }

        NoProxy::from_env().or(None)
    }
}

#[derive(Debug, Clone)]
pub struct Configuration {
    pub(crate) base_path: String,
    pub(crate) client: ClientWithMiddleware,
    pub(crate) bulker: Arc<Mutex<String>>,
    pub(crate) bulker_size: Arc<Mutex<u32>>,
    pub(crate) max_bulk_size: u32,
}

impl Configuration {
    pub fn base_path(&self) -> &str {
        &self.base_path
    }

    pub fn client(&self) -> &ClientWithMiddleware {
        &self.client
    }

    pub fn bulker(&self) -> Arc<Mutex<String>> {
        Arc::clone(&self.bulker)
    }

    pub fn bulker_size(&self) -> Arc<Mutex<u32>> {
        Arc::clone(&self.bulker_size)
    }

    pub fn max_bulk_size(&self) -> u32 {
        self.max_bulk_size
    }
}

impl Configuration {
    pub fn new() -> Configuration {
        Configuration::default()
    }
}

impl Default for Configuration {
    fn default() -> Self {
        Configuration {
            base_path: "http://localhost:9200".to_owned(),
            client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(),
            bulker: Arc::new(Mutex::new(String::new())),
            bulker_size: Arc::new(Mutex::new(0)),
            max_bulk_size: 100,
        }
    }
}