Rust轻量级HTTP客户端库soup2的使用,soup2提供高效简洁的HTTP请求与响应处理功能

soup2-rs

TODO 迁移到 gnome 社区,一旦这个 crate 稳定。

Rust 对 libsoup2 的绑定和包装。

贡献 贡献者,欢迎您!

许可证 soup-sys 可在 MIT 许可证下使用,请参考该许可证。

元数据 pkg:cargo/soup2@0.2.1 超过 3 年前 2021 版本 MIT 59.8 KiB

安装 运行以下 Cargo 命令在您的项目目录中:

cargo add soup2

或者将以下行添加到您的 Cargo.toml:

soup2 = “0.2.1”

所有者 Wu Yuwei Lucas Fernandes Nogueira

以下是一个使用 soup2 进行 HTTP GET 请求的完整示例:

use soup2::prelude::*;
use soup2::Session;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 创建一个新的会话
    let session = Session::new();
    
    // 创建一个 GET 请求
    let request = session.request("GET", "https://httpbin.org/get")?;
    
    // 发送请求并获取响应
    let response = request.send()?;
    
    // 检查响应状态
    if response.status_code() == 200 {
        // 读取响应体
        let body = response.read_to_string()?;
        println!("Response: {}", body);
    } else {
        println!("Request failed with status: {}", response.status_code());
    }
    
    Ok(())
}

以下是一个使用 soup2 进行 POST 请求的完整示例:

use soup2::prelude::*;
use soup2::Session;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 创建一个新的会话
    let session = Session::new();
    
    // 创建一个 POST 请求
    let mut request = session.request("POST", "https://httpbin.org/post")?;
    
    // 设置请求头
    request.set_header("Content-Type", "application/json")?;
    
    // 设置请求体
    let json_data = r#"{"name": "test", "value": 123}"#;
    request.set_body(json_data.as_bytes());
    
    // 发送请求并获取响应
    let response = request.send()?;
    
    // 读取响应体
    let body = response.read_to_string()?;
    println!("Response: {}", body);
    
    Ok(())
}

以下是一个处理异步请求的完整示例:

use soup2::prelude::*;
use soup2::Session;
use std::time::Duration;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 创建一个新的会话
    let session = Session::new();
    
    // 设置超时时间
    session.set_timeout(Some(Duration::from_secs(30)));
    
    // 创建多个并发请求
    let urls = vec![
        "https://httpbin.org/get",
        "https://httpbin.org/ip",
        "https://httpbin.org/user-agent",
    ];
    
    for url in urls {
        let request = session.request("GET", url)?;
        
        // 使用 spawn 异步发送请求
        std::thread::spawn(move || {
            match request.send() {
                Ok(response) => {
                    if let Ok(body) = response.read_to_string() {
                        println!("Response from {}: {}", url, body);
                    }
                }
                Err(e) => println!("Error requesting {}: {}", url, e),
            }
        });
    }
    
    // 等待所有请求完成
    std::thread::sleep(Duration::from_secs(5));
    
    Ok(())
}

完整示例代码:

// 完整示例:使用 soup2-rs 进行 HTTP 请求处理
use soup2::prelude::*;
use soup2::Session;
use std::time::Duration;
use std::thread;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 示例 1: 同步 GET 请求
    println!("=== 同步 GET 请求示例 ===");
    sync_get_request()?;
    
    // 示例 2: 同步 POST 请求
    println!("\n=== 同步 POST 请求示例 ===");
    sync_post_request()?;
    
    // 示例 3: 异步并发请求
    println!("\n=== 异步并发请求示例 ===");
    async_requests()?;
    
    Ok(())
}

// 同步 GET 请求函数
fn sync_get_request() -> Result<(), Box<dyn std::error::Error>> {
    let session = Session::new();
    let request = session.request("GET", "https://httpbin.org/get")?;
    let response = request.send()?;
    
    if response.status_code() == 200 {
        let body = response.read_to_string()?;
        println!("GET 请求成功: {}", body);
    } else {
        println!("GET 请求失败,状态码: {}", response.status_code());
    }
    
    Ok(())
}

// 同步 POST 请求函数
fn sync_post_request() -> Result<(), Box<dyn std::error::Error>> {
    let session = Session::new();
    let mut request = session.request("POST", "https://httpbin.org/post")?;
    
    request.set_header("Content-Type", "application/json")?;
    
    let json_data = r#"{"name": "rust_user", "language": "Rust"}"#;
    request.set_body(json_data.as_bytes());
    
    let response = request.send()?;
    let body = response.read_to_string()?;
    println!("POST 请求响应: {}", body);
    
    Ok(())
}

// 异步请求函数
fn async_requests() -> Result<(), Box<dyn std::error::Error>> {
    let session = Session::new();
    session.set_timeout(Some(Duration::from_secs(10)));
    
    let endpoints = vec![
        ("用户代理", "https://httpbin.org/user-agent"),
        ("IP 地址", "https://httpbin.org/ip"),
        ("Headers", "https://httpbin.org/headers"),
    ];
    
    let mut handles = vec![];
    
    for (name, url) in endpoints {
        let session_clone = session.clone();
        let handle = thread::spawn(move || {
            match session_clone.request("GET", url) {
                Ok(request) => {
                    match request.send() {
                        Ok(response) => {
                            if let Ok(body) = response.read_to_string() {
                                println!("{} 响应: {}", name, body);
                            }
                        }
                        Err(e) => println!("{} 请求错误: {}", name, e),
                    }
                }
                Err(e) => println!("创建 {} 请求失败: {}", name, e),
            }
        });
        handles.push(handle);
    }
    
    // 等待所有线程完成
    for handle in handles {
        handle.join().unwrap();
    }
    
    println!("所有异步请求已完成");
    Ok(())
}

1 回复

Rust轻量级HTTP客户端库soup2使用指南

概述

soup2是一个轻量级、高效简洁的Rust HTTP客户端库,专注于提供简单易用的HTTP请求与响应处理功能。它基于async/await异步编程模型,支持GET、POST等常见HTTP方法,并提供了灵活的响应处理机制。

安装方法

在Cargo.toml中添加依赖:

[dependencies]
soup2 = "0.2"
tokio = { version = "1.0", features = ["full"] }

基本使用方法

1. 发送GET请求

use soup2::prelude::*;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let response = Soup::new()
        .get("https://httpbin.org/get")
        .send()
        .await?;
    
    println!("Status: {}", response.status());
    println!("Body: {}", response.text().await?);
    
    Ok(())
}

2. 发送POST请求

use soup2::prelude::*;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let response = Soup::new()
        .post("https://httpbin.org/post")
        .body(r#"{"name": "Rust", "version": "1.60"}"#)
        .header("Content-Type", "application/json")
        .send()
        .await?;
    
    println!("Response: {}", response.text().await?);
    
    Ok(())
}

3. 处理JSON响应

use soup2::prelude::*;
use serde_json::Value;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let response = Soup::new()
        .get("https://httpbin.org/json")
        .send()
        .await?;
    
    let json: Value = response.json().await?;
    println!("Parsed JSON: {:#?}", json);
    
    Ok(())
}

4. 设置请求超时

use soup2::prelude::*;
use std::time::Duration;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let response = Soup::new()
        .get("https://httpbin.org/delay/5")
        .timeout(Duration::from_secs(3))
        .send()
        .await?;
    
    println!("Response: {}", response.text().await?);
    
    Ok(())
}

5. 自定义请求头

use soup2::prelude::*;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let response = Soup::new()
        .get("https://httpbin.org/headers")
        .header("User-Agent", "soup2-client/1.0")
        .header("Authorization", "Bearer token123")
        .send()
        .await?;
    
    println!("Response headers: {}", response.text().await?);
    
    Ok(())
}

高级功能

错误处理

use soup2::prelude::*;

#[tokio::main]
async fn main() {
    match Soup::new()
        .get("https://invalid-url-that-does-not-exist.com")
        .send()
        .await
    {
        Ok(response) => {
            println!("Success: {}", response.status());
        }
        Err(e) => {
            eprintln!("Request failed: {}", e);
        }
    }
}

流式响应处理

use soup2::prelude::*;
use futures::StreamExt;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut response = Soup::new()
        .get("https://httpbin.org/stream/3")
        .send()
        .await?;
    
    while let Some(chunk) = response.chunk().await? {
        println!("Received chunk: {}", String::from_utf8_lossy(&chunk));
    }
    
    Ok(())
}

性能特点

  • 基于async-std或tokio异步运行时
  • 连接池复用
  • 自动gzip解压缩
  • 支持HTTP/1.1和HTTP/2
  • 零成本抽象

soup2库设计简洁,API直观易用,适合需要轻量级HTTP客户端的Rust项目。

完整示例代码

// 完整示例:使用soup2进行HTTP请求的综合演示
use soup2::prelude::*;
use serde_json::Value;
use std::time::Duration;
use futures::StreamExt;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 示例1:发送GET请求
    println!("=== 发送GET请求示例 ===");
    let get_response = Soup::new()
        .get("https://httpbin.org/get")
        .send()
        .await?;
    println!("状态码: {}", get_response.status());
    println!("响应体: {}", get_response.text().await?);
    
    // 示例2:发送POST请求
    println!("\n=== 发送POST请求示例 ===");
    let post_response = Soup::new()
        .post("https://httpbin.org/post")
        .body(r#"{"name": "Rust", "version": "1.60"}"#)
        .header("Content-Type", "application/json")
        .send()
        .await?;
    println!("POST响应: {}", post_response.text().await?);
    
    // 示例3:处理JSON响应
    println!("\n=== 处理JSON响应示例 ===");
    let json_response = Soup::new()
        .get("https://httpbin.org/json")
        .send()
        .await?;
    let json: Value = json_response.json().await?;
    println!("解析后的JSON: {:#?}", json);
    
    // 示例4:自定义请求头
    println!("\n=== 自定义请求头示例 ===");
    let headers_response = Soup::new()
        .get("https://httpbin.org/headers")
        .header("User-Agent", "soup2-client/1.0")
        .header("Authorization", "Bearer token123")
        .send()
        .await?;
    println!("响应头信息: {}", headers_response.text().await?);
    
    // 示例5:流式响应处理
    println!("\n=== 流式响应处理示例 ===");
    let mut stream_response = Soup::new()
        .get("https://httpbin.org/stream/3")
        .send()
        .await?;
    
    while let Some(chunk) = stream_response.chunk().await? {
        println!("接收到的数据块: {}", String::from_utf8_lossy(&chunk));
    }
    
    Ok(())
}
回到顶部