Rust Tunnel Proxy: reqwest and isahc
Rust reqwest and isahc HTTP clients integrating 16Yun Crawler Proxy.
16Yun Engineering TeamMay 1, 20261 min read
reqwest
reqwest is Rust's most popular HTTP client, configuring proxies via Proxy::all. Note: reqwest does not support injecting custom headers during HTTPS CONNECT, making HTTPS Proxy-Tunnel ineffective.
use reqwest::{Proxy, Client};
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let host = env::var("PROXY_HOST").unwrap_or_else(|_| "t.16yun.cn".into());
let port = env::var("PROXY_PORT").unwrap_or_else(|_| "31111".into());
let user = env::var("PROXY_USERNAME").unwrap_or_else(|_| "user".into());
let pass = env::var("PROXY_PASSWORD").unwrap_or_else(|_| "password".into());
let proxy_url = format!("http://{}:{}@{}:{}", user, pass, host, port);
let proxy = Proxy::all(&proxy_url)?;
let client = Client::builder()
.proxy(proxy)
.timeout(std::time::Duration::from_secs(15))
.build()?;
let resp = client.get("https://httpbin.org/ip").send().await?;
println!("{}", resp.text().await?);
Ok(())
}Proxy-Tunnel Limitations
// HTTP Proxy-Tunnel (valid)
let resp = client.get("http://httpbin.org/ip")
.header("Proxy-Tunnel", "rust-demo")
.send().await?;
// HTTPS Proxy-Tunnel (invalid — reqwest does not support custom headers during CONNECT)
let resp = client.get("https://httpbin.org/ip")
.header("Proxy-Tunnel", "rust-demo") // This header is not sent during CONNECT
.send().await?;| Scenario | reqwest | Description |
|---|---|---|
| A: Force Switch | pool_max_idle_per_host(0) | Disable connection pool |
| B: Keep IP | Default behavior | Reuse connection |
| C-HTTP: Proxy-Tunnel | .header("Proxy-Tunnel", ...) | Send as request header |
| C-HTTPS: Proxy-Tunnel | No (Not supported) | Cannot inject headers during CONNECT |
For HTTPS Proxy-Tunnel, consider Go (
Transport.ProxyConnectHeader) or Python httpx (httpx.Proxy(headers=...)).
isahc
isahc is built on libcurl and supports more proxy features:
use isahc::{HttpClient, Request, auth::Authentication};
use std::env;
fn main() -> Result<(), isahc::Error> {
let host = env::var("PROXY_HOST").unwrap_or_else(|_| "t.16yun.cn".into());
let port = env::var("PROXY_PORT").unwrap_or_else(|_| "31111".into());
let user = env::var("PROXY_USERNAME").unwrap_or_else(|_| "user".into());
let pass = env::var("PROXY_PASSWORD").unwrap_or_else(|_| "password".into());
let client = HttpClient::builder()
.proxy(Some(format!("http://{}:{}", host, port).parse().unwrap()))
.proxy_authentication(Authentication::basic(user, pass))
.timeout(std::time::Duration::from_secs(15))
.build()?;
let resp = client.get("https://httpbin.org/ip")?;
println!("{}", resp.text()?);
Ok(())
}reqwest vs isahc
| Feature | reqwest | isahc |
|---|---|---|
| Async Support | Yes (native async) | Yes |
| Underlying Library | hyper | libcurl |
| HTTPS Tunnel | No | Yes (via libcurl) |
| Ecosystem | Most popular | Smaller |
| API Style | Rust standard | curl-like |
Need an enterprise proxy plan?
We can tailor architecture to your target domains, concurrency, and reliability goals.