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(())
}