good-mitm-core 0.3.0

Use MITM technology to provide features like rewrite, redirect.
Documentation
use crate::error::Error;
use hyper::{client::HttpConnector, Client};
use hyper_proxy::{Proxy as UpstreamProxy, ProxyConnector};
use rustls::client::{ServerCertVerified, ServerCertVerifier};
use std::time::SystemTime;

cfg_if::cfg_if! {
    if #[cfg(feature = "request-native-tls")] {
        use hyper_tls::{HttpsConnector, native_tls::TlsConnector};
    } else {
        use hyper_rustls::{HttpsConnector, HttpsConnectorBuilder};
        use rustls::ClientConfig;
        use std::sync::Arc;
    }
}

#[derive(Clone)]
pub enum HttpClient {
    Proxy(Client<ProxyConnector<HttpsConnector<HttpConnector>>>),
    Https(Client<HttpsConnector<HttpConnector>>),
}

pub fn gen_client(upstream_proxy: Option<UpstreamProxy>) -> Result<HttpClient, Error> {
    cfg_if::cfg_if! {
        if #[cfg(feature = "request-native-tls")] {
            let https = {
                let tls = TlsConnector::builder()
                    .danger_accept_invalid_certs(true)
                    .danger_accept_invalid_hostnames(true)
                    .disable_built_in_roots(true)
                    .build()?;
                let mut http = HttpConnector::new();
                http.enforce_http(false);
                HttpsConnector::from((http, tls.into()))
            };
        } else {
            let https = {
                let https_builder = HttpsConnectorBuilder::new()
                    .with_tls_config({
                        let cert_resolver = Arc::new(TrustAllCertVerifier::default());
                        ClientConfig::builder()
                            .with_safe_defaults()
                            .with_custom_certificate_verifier(cert_resolver)
                            .with_no_client_auth()
                    })
                    .https_or_http()
                    .enable_http1();
                #[cfg(feature = "h2")]
                let https_builder = https_builder.enable_http2();

                https_builder.build()
            };
        }
    }

    if let Some(proxy) = upstream_proxy {
        let connector = ProxyConnector::from_proxy(https, proxy)?;
        return Ok(HttpClient::Proxy(
            Client::builder()
                .http1_title_case_headers(true)
                .http1_preserve_header_case(true)
                .build(connector),
        ));
    } else {
        Ok(HttpClient::Https(
            Client::builder()
                .http1_title_case_headers(true)
                .http1_preserve_header_case(true)
                .build(https),
        ))
    }
}

#[derive(Default)]
struct TrustAllCertVerifier;

impl ServerCertVerifier for TrustAllCertVerifier {
    fn verify_server_cert(
        &self,
        _end_entity: &rustls::Certificate,
        _intermediates: &[rustls::Certificate],
        _server_name: &rustls::ServerName,
        _scts: &mut dyn Iterator<Item = &[u8]>,
        _ocsp_response: &[u8],
        _n_ow: SystemTime,
    ) -> Result<ServerCertVerified, rustls::Error> {
        Ok(ServerCertVerified::assertion())
    }
}