reqres 1.0.0

A pure Rust async HTTP client library based on Tokio with HTTP/2, connection pooling, proxy, cookie, compression, benchmarks, and comprehensive tests
Documentation

reqres

一个 纯 Rust 实现、基于 Tokio 异步、高性能、易用 的 HTTP 客户端库

Crates.io Documentation License

📋 项目简介

reqres 是一个现代化的 HTTP 客户端库,专注于性能和易用性,提供完整的 HTTP 协议支持。

核心特性

  • 完整协议支持:HTTP/1.1、HTTP/2
  • 🚀 高性能:连接池、异步 I/O、零拷贝
  • 🔒 HTTPS 支持:基于 Rustls 的 TLS 实现
  • 🍪 Cookie 管理:自动存储和发送
  • 🗜️ 压缩支持:gzip、deflate、brotli 自动解压
  • 🔌 代理支持:HTTP/HTTPS/SOCKS5 代理配置
  • 🎯 易用 API:Builder 模式、链式调用

性能对比

功能 reqres reqwest ureq hyper
HTTP/1.1
HTTP/2
连接池
Cookie
压缩
代理 🚧
性能
易用性

基准测试结果

连接池性能提升:20-25%
HTTP/2 vs HTTP/1.1:15-20% 提升
Cookie 操作:纳秒级(50-700 ns)

详细基准测试报告:运行 cargo bench

📦 安装

Cargo.toml 中添加:

[dependencies]
reqres = "1.0"

🚀 快速开始

基本请求

use reqres::Client;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new()?;

    // GET 请求
    let response = client.get("https://httpbin.org/get").await?;
    println!("Status: {}", response.status);
    println!("Body: {}", response.text()?);

    Ok(())
}

POST 请求

use reqres::Client;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new()?;

    // POST JSON
    let json_data = serde_json::json!({
        "name": "reqres",
        "version": "1.0.0"
    });
    let response = client.post_json("https://httpbin.org/post", json_data).await?;
    println!("Response: {}", response.text()?);

    Ok(())
}

Cookie 管理

use reqres::{Client, CookieJar};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut cookie_jar = CookieJar::new();
    cookie_jar.insert("session_id".to_string(), "abc123".to_string());

    let client = Client::builder()
        .cookie_jar(cookie_jar)
        .build()?;

    let response = client.get("https://httpbin.org/cookies").await?;
    println!("Response: {}", response.text()?);

    // Cookie 会被自动存储(Set-Cookie 头)

    Ok(())
}

压缩支持

use reqres::Client;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::builder()
        .enable_compression()
        .build()?;

    // 自动发送 Accept-Encoding 并解压响应
    let response = client.get("https://httpbin.org/gzip").await?;
    println!("Response (auto decompressed): {}", response.text()?);

    Ok(())
}

连接池

use reqres::Client;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::builder()
        .enable_pooling()
        .build()?;

    // 多次请求会复用连接
    for i in 0..10 {
        let response = client.get("https://httpbin.org/get").await?;
        println!("Request {}: {}", i, response.status);
    }

    Ok(())
}

HTTP/2

use reqres::Client;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new()?; // 默认启用 HTTP/2

    let response = client.get("https://httpbin.org/get").await?;
    println!("Version: {}", response.version); // HTTP/2.0

    Ok(())
}

代理配置

use reqres::{Client, Proxy, ProxyBuilder, ProxyType};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 从 URL 创建代理
    let proxy = Proxy::from_url("http://proxy.example.com:8080")?;

    // 使用 Builder 创建代理
    let proxy_with_auth = ProxyBuilder::new("proxy.com:3128", ProxyType::Http)
        .credentials("user", "pass")
        .build();

    let client = Client::builder()
        .proxy(proxy)
        .build()?;

    // 注意:实际代理路由尚未实现(框架级支持)

    Ok(())
}

📖 高级用法

自定义配置

use reqres::Client;
use std::time::Duration;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::builder()
        .timeout(Duration::from_secs(30))
        .http2_prior_knowledge()
        .enable_pooling()
        .enable_compression()
        .user_agent("MyApp/1.0")
        .build()?;

    let response = client.get("https://example.com").await?;

    Ok(())
}

请求构建

use reqres::{Client, Request};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new()?;

    let request = Request::get("https://httpbin.org/post")
        .header("X-Custom-Header", "value")
        .body("Hello, world!")
        .build()?;

    let response = client.request(request).await?;

    Ok(())
}

🏗️ 项目结构

reqres/
├── src/
│   ├── lib.rs              # 库入口
│   ├── client.rs           # HTTP 客户端
│   ├── request.rs          # 请求构建
│   ├── response.rs         # 响应处理
│   ├── pool.rs             # 连接池
│   ├── cookie.rs           # Cookie 管理
│   ├── compression.rs      # 压缩/解压
│   ├── proxy.rs            # 代理配置
│   └── error.rs            # 错误类型
├── examples/               # 示例代码
├── benches/                # 基准测试
└── tests/                  # 集成测试

📊 版本路线图

  • ✅ v0.1.0 —— 基础 HTTP/1.1 客户端
  • ✅ v0.2.0 —— HTTPS + Builder 模式
  • ✅ v0.3.0 —— HTTP/2 支持
  • ✅ v0.4.0 —— 连接池 + 性能优化
  • ⏳ v0.5.0 —— HTTP/3(QUIC)支持 [实验性]
  • ✅ v0.6.0 —— 高级功能(代理、Cookie、压缩)
  • ✅ v0.7.0 —— 性能基准测试 + 文档完善
  • ✅ v0.8.0 —— 测试覆盖提升(168个测试)
  • 🎯 v1.0.0 —— 稳定版发布(已发布)

🧪 运行示例

# 运行特定示例
cargo run --example get_request
cargo run --example cookie_request
cargo run --example compression_request
cargo run --example pooling_request

# 运行所有示例
cargo run --examples

📈 基准测试

# 运行所有基准测试
cargo bench

# 运行特定测试
cargo bench pooling
cargo bench cookie
cargo bench http2

# 查看报告
# 报告位置:target/criterion/report/index.html

🤝 贡献

欢迎贡献!请先阅读 开发说明.md 了解开发规范。

📄 许可证

MIT License - 详见 LICENSE

🙏 致谢

本项目借鉴了以下优秀项目:


Made with ❤️ in Rust