89·实战项目高级

实战:HTTP 代理

实战:HTTP 代理

学习目标

  1. 理解 HTTP 代理原理
  2. 使用 reqwest + axum 实现代理
  3. 掌握请求转发

核心实现

use axum::{
    extract::Request,
    response::Response,
    Router, routing::get,
};
use reqwest::Client;

async fn proxy(mut req: Request) -> Response {
    let client = Client::new();
    let path = req.uri().path_and_query()
        .map(|x| x.as_str())
        .unwrap_or("/");

    let target_url = format!("https://httpbin.org{}", path);

    let mut builder = client.request(req.method().clone(), &target_url);

    for (key, value) in req.headers() {
        if key != "host" {
            builder = builder.header(key, value);
        }
    }

    let body = axum::body::to_bytes(req.body_mut(), usize::MAX)
        .await
        .unwrap();

    let resp = builder.body(body).send().await.unwrap();

    let mut response = Response::builder()
        .status(resp.status());

    for (key, value) in resp.headers() {
        response = response.header(key, value);
    }

    response.body(axum::body::Body::from(resp.bytes().await.unwrap())).unwrap()
}

#[tokio::main]
async fn main() {
    let app = Router::new()
        .fallback(proxy);

    let listener = tokio::net::TcpListener::bind("0.0.0.0:8080")
        .await
        .unwrap();

    println!("代理运行在 http://localhost:8080");
    axum::serve(listener, app).await.unwrap();
}

小结

技能应用
reqwest发送 HTTP 请求
axum接收请求
请求转发保持方法和头部

练习编辑器

rust
Loading...