bt_http_utils 0.8.1

A simple HTTP wrapper to simplify POST and GET calls. Default headers with set and get headers. Support cookies. Request generic function for GET, POST, PUT, PATCH, and DELETE.
use std::{env, fs, path::Path};

use bt_logger::{log_error, log_info, log_warning};
use native_tls::{Certificate, TlsConnector};

use crate::{DANGER_ACCEPT_INVALID_CERTS, DANGER_ACCEPT_INVALID_HOSTNAMES};

const LOCAL_CERTIFICATES: &str = "certs";
const LOCAL_CERTIFICATES_ENV_VAR_NAME: &str = "BT_LOCALPEMCERTIFICATES_DIR";

/// Scans the "certs" directory and returns all `.pem` file paths.
fn get_cert_files() -> Vec<String> {
    let mut certs = Vec::new();
    let cert_dir: String = 
    match env::var(LOCAL_CERTIFICATES_ENV_VAR_NAME){
        Ok(d) => d,
        Err(_) => LOCAL_CERTIFICATES.to_owned(),
    };

    if let Ok(entries) = fs::read_dir(&cert_dir) {
        for entry in entries.flatten() {
            let path = entry.path();
            if path.is_file() && path.extension().is_some_and(|ext| ext == "pem") { //map_or(false, |ext| ext == "pem") {
                if let Some(path_str) = path.to_str() {
                    certs.push(path_str.to_string());
                }
            }
        }
    } else {
        log_info!("","Could not read directory '{}'. Assuming no local certificates (PEM files)", &cert_dir);
    }

    certs
}

pub(crate) fn get_local_certificates(danger_accept_invalid: Option<Vec<(String,bool)>>) -> Option<TlsConnector> {
    let certs_str = get_cert_files();
    if certs_str.is_empty() {
        return None
    }

    let mut tls_builder = TlsConnector::builder();
    for cert_path in certs_str {
        if Path::new(&cert_path).exists() {
            match fs::read(&cert_path){
                Ok(cert_bytes) => {
                    match Certificate::from_pem(&cert_bytes){
                        Ok(cert) => {
                                tls_builder.add_root_certificate(cert);
                        },
                        Err(e) => log_error!("", "Could not read PEM file at path: {}. Error: {}",cert_path,e),
                    }
                },
                Err(e) => log_error!("", "Could not read PEM file at path: {}. Error: {}",cert_path,e),
            }
        }else{
            log_error!("", "Invalid certificate path: {}",cert_path);
        }
    }

    if let Some(daiv) = danger_accept_invalid && !daiv.is_empty() {
            for item in daiv {
                if item.0 ==  DANGER_ACCEPT_INVALID_HOSTNAMES {
                    tls_builder.danger_accept_invalid_hostnames(item.1);
                } else {
                    if item.0 == DANGER_ACCEPT_INVALID_CERTS {
                        tls_builder.danger_accept_invalid_certs(item.1);
                    }else{
                        log_warning!("","Inalid Danger Accept Invalid key {}",item.0);
                    }
                }
            }
    }

    match tls_builder.build(){
        Ok(conn) => Some(conn),
        Err(e) => {
            log_error!("","Could not built TLS Connector. Error {}",&e);
            None
        }
    }
}