如何将example.com请求代理到本地IP?Hyper代理服务改造
代理服务中定向example.com到本地IP的实现
我们有一个运行在localhost:8000的简易HTTP代理服务,需要实现:当客户端通过该代理访问example.com时,将请求转发到指定本地IP(示例为192.168.x.x:3000),让客户端误以为example.com指向该本地IP;其余请求则正常转发到实际目标地址,效果类似修改系统hosts文件。
修改后的完整代码
use std::net::SocketAddr; use tower::make::Shared; use hyper::{service::service_fn, Body, Client, Request, Response, Server, Uri}; async fn handle_proxy(mut req: Request<Body>) -> Result<Response<Body>, hyper::Error> { // 获取请求的Host字段 if let Some(host) = req.uri().host() { if host == "example.com" { // 构造新的请求URI,将目标替换为本地服务地址 let new_uri = Uri::builder() // 保留原请求的协议,默认使用http .scheme(req.uri().scheme().cloned().unwrap_or_else(|| "http".parse().unwrap())) // 替换为你的本地IP和端口 .authority("192.168.x.x:3000") // 保留原请求的路径和查询参数 .path_and_query(req.uri().path_and_query().cloned().unwrap_or_default()) .build() .unwrap(); // 更新请求的URI *req.uri_mut() = new_uri; // 保持原Host头不变,让后端服务识别为来自example.com的请求 req.headers_mut().insert( hyper::header::HOST, hyper::header::HeaderValue::from_str(host).unwrap(), ); } } // 创建HTTP客户端并转发请求 let client = Client::new(); client.request(req).await } #[tokio::main] async fn main() { let make_service = Shared::new(service_fn(handle_proxy)); let addr = SocketAddr::from(([127, 0, 0, 1], 8000)); let server = Server::bind(&addr).serve(make_service); if let Err(e) = server.await { eprintln!("服务器错误: {}", e); } }
关键修改说明
- URI重定向:检测到请求Host为
example.com时,重新构造请求URI,将目标地址替换为指定的本地IP和端口,同时保留原请求的协议、路径和查询参数,确保请求内容完整。 - Host头保留:修改URI后,强制保留原请求的
Host: example.com头,这样本地后端服务会认为请求直接来自example.com,和客户端直接访问该域名的行为一致。 - 稳健性处理:对协议部分做了默认值处理,避免因请求URI缺少协议字段导致的错误;使用
unwrap_or_default处理路径参数,确保请求能正常构造。
Cargo.toml配置(无需修改)
[package] name = "my-package" version = "0.1.0" edition = "2021" [dependencies] hyper = { version = "0.14.25", features = ["full"] } tokio = { version = "1.26.0", features = ["full"] } tower = { version = "0.4", features = ["full"] }
内容的提问来源于stack exchange,提问作者aberst
相关产品推荐
相关产品推荐

