rust-proxy 0.1.0

A simple HTTP/HTTPS proxy server written in Rust
use std::io;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::{TcpListener, TcpStream};

/// 简单的TCP代理服务器
pub async fn run_proxy(listen_addr: &str) -> io::Result<()> {
    let listener = TcpListener::bind(listen_addr).await?;
    println!("代理服务器启动,监听地址: {}", listen_addr);

    loop {
        let (client_stream, client_addr) = listener.accept().await?;
        println!("收到来自 {} 的连接", client_addr);

        tokio::spawn(async move {
            if let Err(e) = handle_client(client_stream).await {
                eprintln!("处理客户端连接时出错: {}", e);
            }
        });
    }
}

async fn handle_client(mut client_stream: TcpStream) -> io::Result<()> {
    // 读取客户端请求的第一行(HTTP请求行)
    let mut buffer = [0; 1024];
    let n = client_stream.read(&mut buffer).await?;

    if n == 0 {
        return Ok(());
    }

    let request = String::from_utf8_lossy(&buffer[..n]);
    println!("收到请求:\n{}", request);

    // 解析请求行获取目标主机和端口
    let target_addr = parse_target_addr(&request).unwrap_or_else(|| "httpbin.org:80".to_string());
    println!("连接到目标服务器: {}", target_addr);

    // 连接到目标服务器
    let mut target_stream = TcpStream::connect(&target_addr).await?;

    // 将客户端请求转发到目标服务器
    target_stream.write_all(&buffer[..n]).await?;

    // 在客户端和目标服务器之间双向转发数据
    let (mut client_read, mut client_write) = client_stream.split();
    let (mut target_read, mut target_write) = target_stream.split();

    let client_to_target = tokio::io::copy(&mut client_read, &mut target_write);
    let target_to_client = tokio::io::copy(&mut target_read, &mut client_write);

    // 同时处理两个方向的流量
    tokio::try_join!(client_to_target, target_to_client)?;

    Ok(())
}

fn parse_target_addr(request: &str) -> Option<String> {
    // 简单的解析:查找Host头或从请求行解析
    for line in request.lines() {
        if line.starts_with("GET ") || line.starts_with("POST ") || line.starts_with("HEAD ") {
            // 从请求行解析URL(简化版本)
            let parts: Vec<&str> = line.split_whitespace().collect();
            if parts.len() >= 2 {
                let url = parts[1];
                if url.starts_with("http://") {
                    let url = &url[7..]; // 去掉 "http://"
                    let host_port: Vec<&str> = url.split('/').collect();
                    return Some(host_port[0].to_string());
                }
            }
        } else if line.to_lowercase().starts_with("host: ") {
            let host = line[6..].trim();
            return Some(format!("{}:80", host));
        }
    }

    None
}

#[tokio::main]
async fn main() -> io::Result<()> {
    let listen_addr = "127.0.0.1:8080";
    println!("启动简单的TCP代理服务器...");
    run_proxy(listen_addr).await
}