Rust网络请求库rquest的使用:高效异步HTTP客户端与Rust插件库集成
Rust网络请求库rquest的使用:高效异步HTTP客户端与Rust插件库集成
特性
- 支持多种请求体格式:普通文本、JSON、urlencoded、multipart
- 内置Cookie存储
- 自定义Header顺序
- 重定向策略
- 代理轮换
- 证书存储
- WebSocket升级
- 基于BoringSSL的HTTPS
- HTTP/2 TLS模拟
示例代码
首先需要在Cargo.toml中添加依赖:
[dependencies]
tokio = { version = "1", features = ["full"] }
rquest = "5"
rquest-util = "2"
以下是完整的异步示例代码:
use rquest::Client;
use rquest_util::Emulation;
#[tokio::main]
async fn main() -> Result<(), rquest::Error> {
// 构建客户端并设置Firefox136浏览器模拟
let client = Client::builder()
.emulation(Emulation::Firefox136)
.build()?;
// 发送GET请求并获取响应
let resp = client.get("https://tls.peet.ws/api/all").send().await?;
// 打印响应文本
println!("{}", resp.text().await?);
Ok(())
}
完整示例demo
下面是一个更完整的示例,展示了如何使用rquest发送POST请求并处理JSON响应:
use rquest::Client;
use rquest_util::Emulation;
use serde_json::Value;
use std::collections::HashMap;
#[tokio::main]
async fn main() -> Result<(), rquest::Error> {
// 1. 构建客户端并设置Chrome浏览器模拟
let client = Client::builder()
.emulation(Emulation::Chrome120)
.build()?;
// 2. 准备POST请求数据
let mut data = HashMap::new();
data.insert("username", "testuser");
data.insert("password", "testpass");
// 3. 发送POST请求
let resp = client
.post("https://example.com/api/login")
.json(&data)
.send()
.await?;
// 4. 处理JSON响应
if resp.status().is_success() {
let json: Value = resp.json().await?;
println!("登录成功: {:?}", json);
} else {
println!("请求失败,状态码: {}", resp.status());
}
Ok(())
}
模拟功能说明
HTTP/2 over TLS
- JA3/JA4/Akamai指纹由于TLS加密的复杂性和HTTP/2的普及,无法准确模拟浏览器指纹
- rquest不支持解析这些指纹字符串进行模拟,用户应根据自身需求自定义配置
设备模拟
- 大多数浏览器设备模型共享相同的TLS和HTTP/2配置,仅User-Agent不同
- 浏览器设备模拟模板由rquest-util管理
构建注意事项
避免与依赖openssl-sys
的包一起编译,因为它与boring-sys
共享相同的前缀符号,可能导致链接失败。即使编译成功,同时使用openssl-sys
和boring-sys
也可能导致内存段错误。
安装BoringSSL的构建依赖:
sudo apt-get install build-essential cmake perl pkg-config libclang-dev musl-tools -y
cargo build --release
许可证
Apache-2.0许可证
1 回复
以下是根据您提供的内容整理的完整示例代码,首先展示内容中的示例,然后提供完整的demo实现:
内容中提供的示例汇总
- 基本GET请求示例:
use rquest::Client;
#[tokio::main]
async fn main() -> Result<(), rquest::Error> {
let client = Client::new();
let response = client.get("https://httpbin.org/get")
.send()
.await?;
println!("Status: {}", response.status());
println!("Body: {}", response.text().await?);
Ok(())
}
- POST请求示例:
use rquest::Client;
use std::collections::HashMap;
#[tokio::main]
async fn main() -> Result<(), rquest::Error> {
let client = Client::new();
let mut data = HashMap::new();
data.insert("key", "value");
let response = client.post("https://httpbin.org/post")
.json(&data)
.send()
.await?;
println!("Response: {}", response.text().await?);
Ok(())
}
- 插件系统示例:
use rquest::{Client, Plugin, Request, Response};
use std::time::Instant;
struct TimingPlugin;
#[async_trait::async_trait]
impl Plugin for TimingPlugin {
async fn on_request(&self, request: &mut Request) {
request.extensions_mut().insert(Instant::now());
}
async fn on_response(&self, response: &mut Response) {
if let Some(start) = response.extensions().get::<Instant>() {
let duration = start.elapsed();
println!("Request took {}ms", duration.as_millis());
}
}
}
完整示例Demo
//! 完整的rquest使用示例,包含GET/POST请求、插件系统和错误处理
use rquest::{Client, Plugin, Request, Response, Error};
use std::collections::HashMap;
use std::time::{Instant, Duration};
use async_trait::async_trait;
use futures::future::join_all;
/// 自定义插件:记录请求耗时和状态
struct MetricsPlugin;
#[async_trait]
impl Plugin for MetricsPlugin {
async fn on_request(&self, request: &mut Request) {
request.extensions_mut().insert(Instant::now());
}
async fn on_response(&self, response: &mut Response) {
if let Some(start) = response.extensions().get::<Instant>() {
let duration = start.elapsed();
println!(
"Request to {} took {}ms, status: {}",
response.url(),
duration.as_millis(),
response.status()
);
}
}
}
#[tokio::main]
async fn main() -> Result<(), Error> {
// 1. 创建配置化的客户端
let client = Client::builder()
.timeout(Duration::from_secs(5))
.plugin(MetricsPlugin)
.build();
// 2. 发送GET请求
println!("--- Sending GET request ---");
let get_response = client.get("https://httpbin.org/get")
.header("X-Custom-Header", "Rust")
.send()
.await?;
println!("GET Response status: {}", get_response.status());
println!("GET Body: {}", get_response.text().await?);
// 3. 发送POST请求
println!("\n--- Sending POST request ---");
let mut post_data = HashMap::new();
post_data.insert("name", "rquest");
post_data.insert("version", "0.7");
let post_response = client.post("https://httpbin.org/post")
.json(&post_data)
.send()
.await?;
println!("POST Response: {}", post_response.text().await?);
// 4. 并发请求示例
println!("\n--- Sending concurrent requests ---");
let urls = vec![
"https://httpbin.org/get?req=1",
"https://httpbin.org/get?req=2",
"https://httpbin.org/status/404",
];
let requests = urls.into_iter().map(|url| {
client.get(url).send()
});
let responses = join_all(requests).await;
for response in responses {
match response {
Ok(res) => println!("Concurrent response status: {}", res.status()),
Err(e) => println!("Error: {}", e),
}
}
// 5. 错误处理示例
println!("\n--- Error handling example ---");
match client.get("https://httpbin.org/status/500").send().await {
Ok(res) if res.status().is_success() => {
println!("Request succeeded");
}
Ok(res) => {
println!("Server returned error status: {}", res.status());
}
Err(Error::Timeout) => {
eprintln!("Request timed out");
}
Err(e) => {
eprintln!("Request failed: {}", e);
}
}
Ok(())
}
示例说明
-
客户端配置:
- 设置了5秒超时
- 添加了自定义的MetricsPlugin插件
-
GET请求:
- 添加自定义header
- 打印响应状态和内容
-
POST请求:
- 发送JSON格式数据
- 打印完整响应
-
并发请求:
- 使用join_all同时发送多个请求
- 处理各个请求的结果
-
错误处理:
- 演示了不同错误类型的处理方式
- 包括HTTP错误状态码的处理
这个完整示例展示了rquest库的主要功能:
- 基本的HTTP请求(GET/POST)
- 插件系统的使用
- 并发请求处理
- 详细的错误处理
- 客户端配置选项
使用前请确保Cargo.toml中添加了正确的依赖:
[dependencies]
rquest = "0.7"
tokio = { version = "1.0", features = ["full"] }
async-trait = "0.1"
futures = "0.3"