Skip to content

Instantly share code, notes, and snippets.

@ssrlive
Created January 28, 2023 12:06
Show Gist options
  • Save ssrlive/07ceb19c7f019ea8a8fb754566d07e84 to your computer and use it in GitHub Desktop.
Save ssrlive/07ceb19c7f019ea8a8fb754566d07e84 to your computer and use it in GitHub Desktop.
rust http proxy

Cargo.toml

[dependencies]
anyhow = "1.0.68"
futures-util = "0.3.25"
hyper = { version ="0.14.23", features = ["full"] }
hyper-rustls = "0.23.2"
hyper-tls = "0.5.0"
tokio = { version = "1.24.2", features = ["full"] }

main.rs

use anyhow::Context;
use hyper::{
    service::{make_service_fn, service_fn},
    Body, Client, Request, Server,
};
use std::{net::SocketAddr, sync::Arc};

fn proxy_crates_io_site(req: &mut Request<Body>) -> anyhow::Result<()> {
    for &key in &[
        "content-length",
        "accept-encoding",
        "content-encoding",
        "transfer-encoding",
    ] {
        req.headers_mut().remove(key);
    }
    let uri = req.uri();
    let uri_string = match uri.query() {
        Some(query) => format!("https://crates.io{}?{}", uri.path(), query),
        None => format!("https://crates.io{}", uri.path()),
    };
    *req.uri_mut() = uri_string.parse().context("failed to parse uri")?;
    // *req.headers_mut().insert("HOST", HeaderValue::from_static("crates.io"));
    Ok(())
}

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let connector = hyper_tls::HttpsConnector::new();
    let client = Client::builder().build::<_, Body>(connector);
    let client = Arc::new(client);
    let addr: SocketAddr = ([127, 0, 0, 1], 3000).into();
    let make_service = make_service_fn(move |_| {
        let client = client.clone();
        async move {
            Ok::<_, anyhow::Error>(service_fn(move |mut req| {
                let client = client.clone();
                async move {
                    println!("proxy: {:?}", req);
                    proxy_crates_io_site(&mut req)?;
                    println!("proxy: {:?}", req);
                    client.request(req).await.context("failed to proxy")
                }
            }))
        }
    });
    Server::bind(&addr).serve(make_service).await?;
    Ok(())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment