reqwest_ss_proxy 0.1.9

A reqwest middleware for proxying requests through Shadowsocks. / 一个用于 reqwest 的 Shadowsocks 代理中间件。
Documentation

reqwest_ss_proxy

English | 中文


English

Table of Contents

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.

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(())
}

中文

目录

项目意义

在中国大陆等许多地区,访问全球互联网需要使用代理。Shadowsocks (SS) 是为此目的而生的最流行的代理协议之一。本项目提供了一个 reqwest 中间件,使 Rust 应用程序能够轻松地将其 HTTP/HTTPS 请求通过 Shadowsocks 代理进行路由,从而简化了需要访问受地理限制或防火墙限制资源的应用程序的开发。

技术栈

  • reqwest: 一个符合人体工程学、功能完备的 Rust HTTP 客户端。
  • reqwest-middleware: 一个用于为 reqwest 创建和链接中间件的框架。
  • shadowsocks-rust: 一个健壮且高效的 Shadowsocks 协议实现。
  • tokio: Rust 的异步运行时。
  • anyhow: 用于灵活、便捷的错误处理。

设计思路

设计遵循简单性和惯例集成的原则。该中间件应可作为任何已使用 reqwestreqwest-middleware 项目的即插即用组件。它暴露了最小化的 API——主要是 SsMiddleware::from_url——以保持设置过程的直接性。它的目标是在操作上保持透明,无缝地代理请求,而无需更改应用程序的请求构建逻辑。

文件结构

.
├── Cargo.toml       # 项目清单和依赖项
├── src
│   ├── lib.rs       # 主库入口点,导出中间件
│   ├── reqwest.rs   # SsMiddleware 的核心实现
│   └── error.rs     # 库的自定义错误类型
└── tests
    └── main.rs      # 集成测试

使用演示

这是一个如何将 SsMiddlewarereqwest_middleware::ClientBuilder 结合使用的示例,参考自 tests/main.rs

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.

关于

本项目为 i18n.site ⋅ 国际化解决方案 的开源组件。