proxy_http 0.1.1

An HTTP proxy server that supports forwarding requests to upstream proxies. / 一个支持转发请求到上游代理的 HTTP 代理服务器。
Documentation
# proxy_http

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

<a id="english"></a>

## English

- [Introduction](#introduction)
- [Tech Stack](#tech-stack)
- [Usage](#usage)
- [File Structure](#file-structure)
- [A Little History](#a-little-history)

### Introduction

`proxy_http` is a lightweight, asynchronous HTTP proxy server built with Rust. Its core feature is the ability to route outgoing traffic through a series of upstream proxy servers, which are dynamically fetched and managed. It's designed for scenarios requiring IP rotation, enhanced anonymity, or bypassing network restrictions. The server supports basic authentication to control access.

### Tech Stack

This project leverages modern and efficient Rust libraries to achieve high performance and reliability:

- **[Tokio](https://tokio.rs/)**: An asynchronous runtime for writing fast and reliable network applications.
- **[Hyper](https://hyper.rs/)**: A fast and correct HTTP implementation for Rust, used as the foundation of the proxy server.
- **[Reqwest](https://github.com/seanmonstar/reqwest)**: An ergonomic, higher-level HTTP client, used for testing the proxy functionality.
- **[ThisError](https://github.com/dtolnay/thiserror)**: A library for deriving `std::error::Error` implementations for custom error types.

### Usage

The following example demonstrates how to initialize the proxy server and make a request through it. The server will fetch a list of upstream proxies and use them to forward the client's request.

First, start the proxy server:

```rust
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
use aok::{OK, Void};
use log::info;

// Assume SS_SUBSCRIPTION_URL is set in the environment
genv::s!(SS_SUBSCRIPTION_URL: String);

async fn run_proxy_server() -> Void {
  // Fetch upstream proxy providers from a subscription URL
  let fetch = proxy_fetch::load(SS_SUBSCRIPTION_URL.split(";")).await?;

  let user = "test";
  let password = "pwd";
  let port = 32342;
  let addr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), port));

  // Run the proxy server in a separate task
  tokio::spawn(async move {
    xerr::log!(proxy_http::run(fetch, addr, user, &password).await);
  });

  tokio::time::sleep(tokio::time::Duration::from_millis(500)).await;
  OK
}
```

Then, use a client like `reqwest` to make a request through the proxy server with basic authentication:

```rust
async fn client_request() -> Void {
  let user = "test";
  let password = "pwd";
  let port = 32342;
  let url = "http://ifconfig.me/ip";

  // Configure the client to use the proxy
  let proxy = reqwest::Proxy::http(format!("http://{user}:{password}@127.0.0.1:{port}"))?;
  let client = reqwest::Client::builder().proxy(proxy).build()?;

  // Send the request
  let res = client.get(url).send().await?;
  let ip = res.text().await?;
  info!("IP via proxy: {ip}");
  assert!(!ip.is_empty());

  OK
}
```

### File Structure

The project is organized as follows:

- `Cargo.toml`: Defines project metadata, dependencies, and build settings.
- `src/main.rs`: The main entry point for the executable, responsible for initializing and running the proxy server.
- `src/lib.rs`: The library core, containing the primary proxy logic, including request handling, authentication, and forwarding.
- `src/error.rs`: Defines custom error types for the application using `thiserror`.
- `tests/main.rs`: Contains integration tests that verify the end-to-end functionality of the proxy server.

### A Little History

The concept of proxy servers is nearly as old as the web itself. The first proxies were developed at CERN in the early 1990s, around the same time Tim Berners-Lee was creating the World Wide Web. Initially, they were used as "gateways" to handle different protocols, but their role quickly evolved into caching, which was crucial for reducing traffic on the slow and expensive international networks of the time. This simple yet powerful idea of an intermediary has since become a fundamental building block of modern network architecture, enabling everything from security and content filtering to the very distributed systems this project relies on.

---

<a id="chinese"></a>

## 中文

- [项目简介](#项目简介)
- [技术栈](#技术栈)
- [使用演示](#使用演示)
- [文件结构](#文件结构)
- [相关历史](#相关历史)

### 项目简介

`proxy_http` 是一个使用 Rust 构建的轻量级、异步 HTTP 代理服务器。其核心功能是能够将出站流量通过一系列动态获取和管理上游代理服务器进行路由。它专为需要 IP 轮换、增强匿名性或绕过网络限制的场景而设计。服务器支持基本身份验证以控制访问。

### 技术栈

本项目利用了现代化且高效的 Rust 库,以实现卓越的性能和可靠性:

- **[Tokio](https://tokio.rs/)**: 一个用于编写快速、可靠网络应用的异步运行时。
- **[Hyper](https://hyper.rs/)**: 一个快速且正确的 Rust HTTP 实现,用作代理服务器的基础。
- **[Reqwest](https://github.com/seanmonstar/reqwest)**: 一个符合人体工程学的高级 HTTP 客户端,用于测试代理功能。
- **[ThisError](https://github.com/dtolnay/thiserror)**: 一个用于为自定义错误类型派生 `std::error::Error` 实现的库。

### 使用演示

以下示例演示了如何初始化代理服务器并通过它发出请求。服务器将获取一个上游代理列表,并使用它们来转发客户端的请求。

首先,启动代理服务器:

```rust
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
use aok::{OK, Void};
use log::info;

// 假设环境变量中设置了 SS_SUBSCRIPTION_URL
genv::s!(SS_SUBSCRIPTION_URL: String);

async fn run_proxy_server() -> Void {
  // 从订阅 URL 获取上游代理提供者
  let fetch = proxy_fetch::load(SS_SUBSCRIPTION_URL.split(";")).await?;

  let user = "test";
  let password = "pwd";
  let port = 32342;
  let addr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), port));

  // 在一个独立的任务中运行代理服务器
  tokio::spawn(async move {
    xerr::log!(proxy_http::run(fetch, addr, user, &password).await);
  });

  tokio::time::sleep(tokio::time::Duration::from_millis(500)).await;
  OK
}
```

然后,使用像 `reqwest` 这样的客户端,通过基本身份验证向代理服务器发出请求:

```rust
async fn client_request() -> Void {
  let user = "test";
  let password = "pwd";
  let port = 32342;
  let url = "http://ifconfig.me/ip";

  // 配置客户端以使用代理
  let proxy = reqwest::Proxy::http(format!("http://{user}:{password}@127.0.0.1:{port}"))?;
  let client = reqwest::Client::builder().proxy(proxy).build()?;

  // 发送请求
  let res = client.get(url).send().await?;
  let ip = res.text().await?;
  info!("通过代理获取的 IP: {ip}");
  assert!(!ip.is_empty());

  OK
}
```

### 文件结构

项目结构组织如下:

- `Cargo.toml`: 定义项目元数据、依赖项和构建配置。
- `src/main.rs`: 可执行文件的主入口点,负责初始化和运行代理服务器。
- `src/lib.rs`: 库的核心,包含主要的代理逻辑,如请求处理、身份验证和转发。
- `src/error.rs`: 使用 `thiserror` 为应用程序定义自定义错误类型。
- `tests/main.rs`: 包含集成测试,用于验证代理服务器的端到端功能。

### 相关历史

代理服务器的概念几乎与万维网本身一样古老。最早的代理是 1990 年代初在欧洲核子研究中心(CERN)开发的,大约在蒂姆·伯纳斯-李(Tim Berners-Lee)创建万维网的同一时期。最初,它们被用作处理不同协议的“网关”,但其角色很快演变为缓存,这对于在当时缓慢而昂贵的国际网络上减少流量至关重要。这个简单而强大的中介理念,后来成为现代网络架构的基本构建块,支撑着从安全、内容过滤到本项目所依赖的分布式系统等各种技术。

<+ ../about.md >