reqwest_proxy 0.1.7

Seamlessly proxy reqwest traffic through Shadowsocks, Hysteria2, and more. / 通过 Shadowsocks、Hysteria2 等多种协议无缝代理 reqwest 流量。
# reqwest_proxy

[English](#english) | [中文](#中文)

---

## English

<a name="english"></a>

### Table of Contents

- [Project Significance](#project-significance)
- [Features](#features)
- [Design Philosophy](#design-philosophy)
- [Usage](#usage)
- [Tech Stack](#tech-stack)
- [File Structure](#file-structure)
- [A Little Story](#a-little-story)

---

### Project Significance

Applications often require routing traffic through proxies to ensure reliable network access across restricted regions. `reqwest_proxy` is a middleware for the Rust `reqwest` ecosystem that enables this.

It allows applications to route HTTP/HTTPS requests through specified proxy protocols. By abstracting connection details, it helps developers build applications that operate consistently across different network environments.

### Features

- **Protocol Support**: Implements **Shadowsocks** and **Hysteria2**.
- **Seamless Integration**: Designed as a `reqwest-middleware` component for easy integration into projects using `reqwest`.
- **Unified API**: Provides a single entry point, `Proxy::from_url`, to configure different proxy types from a URL string.
- **Asynchronous**: Built on `tokio` for non-blocking I/O.

### Design Philosophy

The design is centered on abstracting protocol-specific implementations behind a unified interface.

The core component is the `Proxy` enum, which functions as the middleware. The call flow is as follows:

1.  A proxy server URL (e.g., `ss://...` or `hysteria2://...`) is provided.
2.  The `Proxy::from_url` function parses the URL, identifies the protocol, and initializes the corresponding client connector.
3.  The resulting `Proxy` instance is attached to the `reqwest_middleware::ClientBuilder`.
4.  When a request is sent, the middleware intercepts it, establishing a connection to the destination through the proxy server via a configured `hyper::Client`.

This design allows developers to switch proxy protocols by changing the configuration URL, with no changes to application logic.

### Usage

This example, based on `tests/main.rs`, demonstrates integrating `reqwest_proxy` with `reqwest_middleware::ClientBuilder`.

First, enable the required features in `Cargo.toml`:
```toml
[dependencies]
reqwest_proxy = { version = "0.1", features = ["full"] }
```

Next, use the `Proxy` middleware in the application:
```rust
use anyhow::Result;
use reqwest_middleware::{ClientBuilder, ClientWithMiddleware};
use reqwest_proxy::Proxy;

#[tokio::main]
async fn main() -> Result<()> {
    // 1. Define the proxy server URL.
    //    This example uses Shadowsocks; Hysteria2 is also supported.
    let proxy_url = "ss://aes-256-gcm:password@your-server-address:port";

    // 2. Create a Proxy middleware instance from the URL.
    let proxy_middleware = Proxy::from_url(proxy_url)?;

    // 3. Build a reqwest client and attach the middleware.
    //    Disabling the system proxy ensures traffic routes through the specified proxy.
    let client: ClientWithMiddleware = ClientBuilder::new(
        reqwest::Client::builder().no_proxy().build()?
    ).with(proxy_middleware).build();

    // 4. Use the client to send requests.
    //    The traffic will be automatically proxied.
    let test_url = "https://ifconfig.me/ip";
    match client.get(test_url).send().await {
        Ok(res) => {
            let status = res.status();
            let ip = res.text().await?;
            // The IP printed should be that of the proxy server.
            println!("Request to {test_url}: Status={status}, IP={ip}");
        }
        Err(e) => {
            eprintln!("Request to {test_url} failed: {e}");
        }
    }

    Ok(())
}
```

### Tech Stack

*   **`reqwest`**: An ergonomic HTTP client for Rust.
*   **`reqwest-middleware`**: A framework for creating middleware for `reqwest`.
*   **`tokio`**: An asynchronous runtime for network applications.
*   **`hyper`**: A low-level HTTP library that powers `reqwest`.
*   **`shadowsocks-rust`**: A Rust implementation of the Shadowsocks protocol.
*   **`hysteria2`**: The core library for the Hysteria2 protocol.
*   **`thiserror`**: A library for deriving error types.

### File Structure

The `src` directory is organized for modularity and feature-based compilation:
```
src
├── error.rs       # Defines custom error types for the library.
├── hysteria2.rs   # Implements the Hysteria2 protocol connector.
├── lib.rs         # Main library entry point, assembling the public API.
├── macro_conn.rs  # Macro to reduce boilerplate for connection types.
├── macro_enums.rs # Macro that generates enums for unifying protocols.
├── middleware.rs  # Contains the primary `ProxyMiddleware` logic.
├── shadowsocks.rs # Implements the Shadowsocks protocol connector.
├── stream.rs      # Provides a unified `Stream` wrapper for `hyper`.
├── traits.rs      # Defines common traits for protocol implementations.
└── util.rs        # Utility functions.
```

### A Little Story

The development of proxy protocols is a response to evolving network filtering techniques. As network surveillance advanced, so did the need for traffic obfuscation.

**Shadowsocks**, created in 2012 by the programmer "clowwindy," was a significant step. It introduced a lightweight, encrypted SOCKS5 proxy protocol designed to be less distinguishable from regular HTTPS traffic, making it harder for automated systems to detect. Its open-source nature allowed a community to maintain and evolve it after the original author ceased development.

Later, protocols like **Hysteria2** emerged, built on the QUIC transport protocol. It focuses on maximizing throughput and minimizing latency, even on networks with high packet loss, while masquerading as standard HTTP/3 traffic. The progression from Shadowsocks to Hysteria2 shows continued innovation in the field, moving from simple obfuscation to performance-oriented designs.

---

## 中文

<a name="中文"></a>

### 目录

- [项目意义](#项目意义-1)
- [功能特性](#功能特性-1)
- [设计思路](#设计思路-1)
- [使用演示](#使用演示-1)
- [技术栈](#技术栈-1)
- [文件结构](#文件结构-1)
- [相关故事](#相关故事-1)

---

### 项目意义

应用程序常需通过代理路由流量,以确保在受限区域内网络的可靠访问。`reqwest_proxy` 是为 Rust `reqwest` 生态系统提供的中间件,旨在实现此功能。

它允许应用程序通过指定的代理协议路由 HTTP/HTTPS 请求。通过抽象连接细节,它帮助开发者构建在不同网络环境中表现一致的应用程序。

### 功能特性

- **协议支持**: 实现 **Shadowsocks** 和 **Hysteria2** 协议。
- **无缝集成**: 设计为 `reqwest-middleware` 组件,便于集成到使用 `reqwest` 的项目中。
- **统一接口**: 提供 `Proxy::from_url` 入口点,可通过 URL 字符串配置不同类型的代理。
- **异步**: 基于 `tokio` 构建,用于非阻塞 I/O。

### 设计思路

设计的核心是将特定协议的实现抽象在统一的接口之后。

`Proxy` 枚举是核心组件,作为中间件运行。其调用流程如下:

1.  提供代理服务器的 URL (例如 `ss://...` 或 `hysteria2://...`)。
2.  `Proxy::from_url` 函数解析 URL,识别协议,并初始化相应的客户端连接器。
3.  生成的 `Proxy` 实例被附加到 `reqwest_middleware::ClientBuilder`。
4.  发送请求时,中间件会拦截该请求,并通过已配置的 `hyper::Client` 经由代理服务器建立到目标的连接。

此设计允许开发者通过更改配置 URL 来切换代理协议,而无需修改应用程序逻辑。

### 使用演示

此示例基于 `tests/main.rs`,演示了如何将 `reqwest_proxy` 与 `reqwest_middleware::ClientBuilder` 集成。

首先,在 `Cargo.toml` 中启用所需的功能:
```toml
[dependencies]
reqwest_proxy = { version = "0.1", features = ["full"] }
```

接下来,在应用程序中使用 `Proxy` 中间件:
```rust
use anyhow::Result;
use reqwest_middleware::{ClientBuilder, ClientWithMiddleware};
use reqwest_proxy::Proxy;

#[tokio::main]
async fn main() -> Result<()> {
    // 1. 定义代理服务器 URL。
    //    此示例使用 Shadowsocks;也支持 Hysteria2。
    let proxy_url = "ss://aes-256-gcm:password@your-server-address:port";

    // 2. 从 URL 创建 Proxy 中间件实例。
    let proxy_middleware = Proxy::from_url(proxy_url)?;

    // 3. 构建 reqwest 客户端并附加中间件。
    //    禁用系统代理可确保流量通过指定的代理路由。
    let client: ClientWithMiddleware = ClientBuilder::new(
        reqwest::Client::builder().no_proxy().build()?
    ).with(proxy_middleware).build();

    // 4. 使用客户端发送请求。
    //    流量将被自动代理。
    let test_url = "https://ifconfig.me/ip";
    match client.get(test_url).send().await {
        Ok(res) => {
            let status = res.status();
            let ip = res.text().await?;
            // 打印出的 IP 应为代理服务器的 IP。
            println!("请求 {test_url}: Status={status}, IP={ip}");
        }
        Err(e) => {
            eprintln!("请求 {test_url} 失败: {e}");
        }
    }

    Ok(())
}
```

### 技术栈

*   **`reqwest`**: Rust 的 HTTP 客户端。
*   **`reqwest-middleware`**: 用于为 `reqwest` 创建中间件的框架。
*   **`tokio`**: 用于网络应用程序的异步运行时。
*   **`hyper`**: 为 `reqwest` 提供支持的底层 HTTP 库。
*   **`shadowsocks-rust`**: Shadowsocks 协议的 Rust 实现。
*   **`hysteria2`**: Hysteria2 协议的核心库。
*   **`thiserror`**: 用于派生错误类型的库。

### 文件结构

`src` 目录为实现模块化和基于功能的编译而组织:
```
src
├── error.rs       # 定义库的自定义错误类型。
├── hysteria2.rs   # 实现 Hysteria2 协议连接器。
├── lib.rs         # 主库入口点,组装公共 API。
├── macro_conn.rs  # 用于减少连接类型样板代码的宏。
├── macro_enums.rs # 生成枚举以统一协议的宏。
├── middleware.rs  # 包含 `ProxyMiddleware` 的主要逻辑。
├── shadowsocks.rs # 实现 Shadowsocks 协议连接器。
├── stream.rs      # 为 `hyper` 提供统一的 `Stream` 包装器。
├── traits.rs      # 定义协议实现的通用 trait。
└── util.rs        # 工具函数。
```

### 相关故事

代理协议的开发是为了应对不断演进的网络过滤技术。随着网络审查技术的发展,流量混淆的需求也随之增加。

**Shadowsocks** 由程序员 "clowwindy" 于2012年创建,是此领域的一项重要进展。它引入了轻量级、加密的 SOCKS5 代理协议,其设计使其流量特征与普通 HTTPS 流量难以区分,从而增加了自动化系统检测的难度。其开源属性使得社区能够在原作者停止开发后继续维护和发展。

随后,出现了基于 QUIC 传输协议构建的 **Hysteria2** 等协议。它专注于最大化吞吐量和最小化延迟,即使在有高丢包率的网络上也能保持性能,同时将流量伪装成标准的 HTTP/3 流量。从 Shadowsocks 到 Hysteria2 的演进,展示了该领域从简单的流量混淆到以性能为导向的设计的持续创新。

<+ ../about.md >