Warp proxy (http) server with Hyper (https "dangerous") client [code sample]

Cargo.toml


[dependencies]
futures = "0.3.13"
hyper = "0.14.4"
hyper-tls = "0.5.0"
native-tls = "0.2.7"
tokio = { version = "1.2.0", features = ["full"] }
warp = "0.3.0"

main.rs


use futures::TryFutureExt;
use warp::Filter;

#[tokio::main]
pub async fn main() {
    let address: std::net::SocketAddr = ([127, 0, 0, 1], 8080).into();

    let routes = warp::any()
        .and(warp::method())
        .and(warp::path::full())
        .and(
            warp::filters::query::raw()
                .or(warp::any().map(|| String::default()))
                .unify(),
        )
        .and(warp::header::headers_cloned())
        .and(warp::body::bytes())
        .map(
            |method: hyper::http::Method,
             path: warp::path::FullPath,
             query_params: String,
             headers: hyper::http::HeaderMap,
             body: hyper::body::Bytes| {
                let mut full_path = path.as_str().to_string();
                if query_params != "" {
                    full_path = format!("{}?{}", full_path, query_params);
                }
                let mut hyper_request = hyper::http::Request::builder()
                    .method(method)
                    .uri(full_path)
                    .body(hyper::body::Body::from(body))
                    .expect("Request::builder() failed");
                {
                    *hyper_request.headers_mut() = headers;
                }
                hyper_request
            },
        )
        .and_then(|hyper_request: hyper::Request<:body>| {
            handler(hyper_request).map_err(|_e| warp::reject::reject())
        });

    println!("Serving at: {}", address.to_string());
    warp::serve(routes).run(address).await;
}

async fn handler(
    mut request: hyper::Request<:body>,
) -> Result<:response>, warp::Rejection> {
    // Make the client a global shareable client. This is just an example.
    let tls = native_tls::TlsConnector::builder()
        .danger_accept_invalid_hostnames(true)
        .danger_accept_invalid_certs(true)
        .build()
        .unwrap();
    let mut http = hyper::client::HttpConnector::new();
    http.enforce_http(false);
    let https: hyper_tls::HttpsConnector<:client::httpconnector>> = hyper_tls::HttpsConnector::from((http, tls.into()));
    let client: hyper::Client<:httpsconnector>>, hyper::Body> = hyper::Client::builder().build::<_, hyper::Body>(https);

    // Manipulate the uri to your liking.
    *request.uri_mut() = "http://httpbin.org/ip"
        .parse()
        .expect("Failed to parse the uri");

    let response = client.request(request).await.expect("Request failed");
    Ok(response)
}
<:client::httpconnector><:client::connect::dns::gairesolver><:body>
Tags