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