# reqwest_ss_proxy
---
## English
### Table of Contents
- [Project Significance](#project-significance)
- [Tech Stack](#tech-stack)
- [Design Philosophy](#design-philosophy)
- [File Structure](#file-structure)
- [Usage](#usage)
### Project Significance
In many regions, such as mainland China, accessing the global internet requires a proxy. Shadowsocks (SS) is one of the most popular proxy protocols for this purpose. This project provides a `reqwest` middleware that enables Rust applications to easily route their HTTP/HTTPS requests through a Shadowsocks proxy, simplifying development for applications that need to access geo-restricted or firewalled resources.
### Tech Stack
* **`reqwest`**: An ergonomic, batteries-included HTTP client for Rust.
* **`reqwest-middleware`**: A framework for creating and chaining middleware for `reqwest`.
* **`shadowsocks-rust`**: A robust and efficient implementation of the Shadowsocks protocol.
* **`tokio`**: The asynchronous runtime for Rust.
* **`anyhow`**: For flexible and easy error handling.
### Design Philosophy
The design is guided by simplicity and idiomatic integration. The middleware should be a drop-in component for any project already using `reqwest` and `reqwest-middleware`. It exposes a minimal API—primarily `SsMiddleware::from_url`—to keep the setup process straightforward. It aims to be transparent in its operation, seamlessly proxying requests without requiring changes to the application's request-building logic.
### File Structure
```
.
├── Cargo.toml # Project manifest and dependencies
├── src
│ ├── lib.rs # Main library entry point, exports the middleware
│ ├── reqwest.rs # Core implementation of the SsMiddleware
│ └── error.rs # Custom error types for the library
└── tests
└── main.rs # Integration tests
```
### Usage
Here is an example of how to use `SsMiddleware` with `reqwest_middleware::ClientBuilder`, based on `tests/main.rs`.
```rust
use anyhow::Result;
use reqwest_middleware::{ClientBuilder, ClientWithMiddleware};
use reqwest_ss_proxy::SsMiddleware;
#[tokio::main]
async fn main() -> Result<()> {
// 1. Create the SsMiddleware from your Shadowsocks URL.
// Replace with your Shadowsocks server URL.
let url = "ss://aes-256-gcm:password@server:port";
// 2. Build the reqwest client with the middleware.
let ss_middleware = SsMiddleware::from_url(url)?;
let client: ClientWithMiddleware =
ClientBuilder::new(reqwest::Client::new()).with(ss_middleware).build();
// 3. Send requests through the proxy.
for test_url in ["http://ifconfig.me/ip", "https://ifconfig.me/ip"] {
match client.get(test_url).send().await {
Ok(res) => {
let status = res.status();
let ip = res.text().await?;
println!("Request to {test_url}: Status={status}, IP={ip}");
}
Err(e) => {
eprintln!("Request to {test_url} failed: {e}");
}
}
}
Ok(())
}
```
---
## 中文
### 目录
- [项目意义](#项目意义)
- [技术栈](#技术栈)
- [设计思路](#设计思路)
- [文件结构](#文件结构-1)
- [使用演示](#使用演示)
### 项目意义
在中国大陆等许多地区,访问全球互联网需要使用代理。Shadowsocks (SS) 是为此目的而生的最流行的代理协议之一。本项目提供了一个 `reqwest` 中间件,使 Rust 应用程序能够轻松地将其 HTTP/HTTPS 请求通过 Shadowsocks 代理进行路由,从而简化了需要访问受地理限制或防火墙限制资源的应用程序的开发。
### 技术栈
* **`reqwest`**: 一个符合人体工程学、功能完备的 Rust HTTP 客户端。
* **`reqwest-middleware`**: 一个用于为 `reqwest` 创建和链接中间件的框架。
* **`shadowsocks-rust`**: 一个健壮且高效的 Shadowsocks 协议实现。
* **`tokio`**: Rust 的异步运行时。
* **`anyhow`**: 用于灵活、便捷的错误处理。
### 设计思路
设计遵循简单性和惯例集成的原则。该中间件应可作为任何已使用 `reqwest` 和 `reqwest-middleware` 项目的即插即用组件。它暴露了最小化的 API——主要是 `SsMiddleware::from_url`——以保持设置过程的直接性。它的目标是在操作上保持透明,无缝地代理请求,而无需更改应用程序的请求构建逻辑。
### 文件结构
```
.
├── Cargo.toml # 项目清单和依赖项
├── src
│ ├── lib.rs # 主库入口点,导出中间件
│ ├── reqwest.rs # SsMiddleware 的核心实现
│ └── error.rs # 库的自定义错误类型
└── tests
└── main.rs # 集成测试
```
### 使用演示
这是一个如何将 `SsMiddleware` 与 `reqwest_middleware::ClientBuilder` 结合使用的示例,参考自 `tests/main.rs`。
```rust
use anyhow::Result;
use reqwest_middleware::{ClientBuilder, ClientWithMiddleware};
use reqwest_ss_proxy::SsMiddleware;
#[tokio::main]
async fn main() -> Result<()> {
// 1. 从你的 Shadowsocks URL 创建 SsMiddleware。
// 请替换为你的 Shadowsocks 服务器 URL。
let url = "ss://aes-256-gcm:password@server:port";
// 2. 使用中间件构建 reqwest 客户端。
let ss_middleware = SsMiddleware::from_url(url)?;
let client: ClientWithMiddleware =
ClientBuilder::new(reqwest::Client::new()).with(ss_middleware).build();
// 3. 通过代理发送请求。
for test_url in ["http://ifconfig.me/ip", "https://ifconfig.me/ip"] {
match client.get(test_url).send().await {
Ok(res) => {
let status = res.status();
let ip = res.text().await?;
println!("请求 {test_url}: Status={status}, IP={ip}");
}
Err(e) => {
eprintln!("请求 {test_url} 失败: {e}");
}
}
}
Ok(())
}
```
## About
This project is an open-source component of [i18n.site ⋅ Internationalization Solution](https://i18n.site).
* [i18 : MarkDown Command Line Translation Tool](https://i18n.site/i18)
The translation perfectly maintains the Markdown format.
It recognizes file changes and only translates the modified files.
The translated Markdown content is editable; if you modify the original text and translate it again, manually edited translations will not be overwritten (as long as the original text has not been changed).
* [i18n.site : MarkDown Multi-language Static Site Generator](https://i18n.site/i18n.site)
Optimized for a better reading experience
## 关于
本项目为 [i18n.site ⋅ 国际化解决方案](https://i18n.site) 的开源组件。
* [i18 : MarkDown 命令行翻译工具](https://i18n.site/i18)
翻译能够完美保持 Markdown 的格式。能识别文件的修改,仅翻译有变动的文件。
Markdown 翻译内容可编辑;如果你修改原文并再次机器翻译,手动修改过的翻译不会被覆盖 ( 如果这段原文没有被修改 )。
* [i18n.site : MarkDown 多语言静态站点生成器](https://i18n.site/i18n.site) 为阅读体验而优化。