Rust语言从入门到精通系列 - Http客户端reqwest模块实战

1478 字
7 分钟
Rust语言从入门到精通系列 - Http客户端reqwest模块实战

Reqwest 是一个 Rust 语言的 HTTP 客户端库,它提供了简单易用的 API,可以发送 HTTP 请求并处理响应。Reqwest 支持同步和异步操作,可以用于编写 Web 服务,爬虫,测试等应用。

基础用法#

发送 GET 请求#

use reqwest::blocking::Client;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new();
let response = client.get("https://httpbin.org/get").send()?;
println!("{}", response.text()?);
Ok(())
}

这个例子中,我们使用 blocking 模块中的 Client 创建了一个 HTTP 客户端,然后使用 get 方法发送了一个 GET 请求,请求了 httpbin.org 的/get 接口,并使用 text 方法获取响应内容。

发送 POST 请求#

use reqwest::blocking::Client;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new();
let response = client.post("https://httpbin.org/post")
.body("hello world")
.send()?;
println!("{}", response.text()?);
Ok(())
}

这个例子中,我们使用 post 方法发送了一个 POST 请求,请求了 httpbin.org 的/post 接口,并使用 body 方法设置请求体。

发送 JSON 请求#

use reqwest::blocking::Client;
use serde_json::json;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new();
let data = json!({
"name": "Alice",
"age": 20
});
let response = client.post("https://httpbin.org/post")
.json(&data)
.send()?;
println!("{}", response.text()?);
Ok(())
}

这个例子中,我们使用 json!宏创建了一个 JSON 对象,然后使用 json 方法设置请求体,发送了一个 POST 请求。

发送表单请求#

use reqwest::blocking::Client;
use std::collections::HashMap;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new();
let mut data = HashMap::new();
data.insert("name", "Alice");
data.insert("age", "20");
let response = client.post("https://httpbin.org/post")
.form(&data)
.send()?;
println!("{}", response.text()?);
Ok(())
}

这个例子中,我们使用 HashMap 创建了一个表单数据,然后使用 form 方法设置请求体,发送了一个 POST 请求。

发送带有 Header 的请求#

use reqwest::blocking::Client;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new();
let response = client.get("https://httpbin.org/get")
.header("X-My-Header", "hello")
.send()?;
println!("{}", response.text()?);
Ok(())
}

这个例子中,我们使用 header 方法设置了一个自定义的 Header,发送了一个 GET 请求。

use reqwest::blocking::Client;
use reqwest::header::COOKIE;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new();
let response = client.get("https://httpbin.org/get")
.header(COOKIE, "name=value")
.send()?;
println!("{}", response.text()?);
Ok(())
}

这个例子中,我们使用 header 方法设置 Cookie 请求头(reqwest::cookie::Cookie::new() 在新版中不可用,推荐直接通过 Header 设置 Cookie)。

发送带有代理的请求#

use reqwest::blocking::Client;
use reqwest::Proxy;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::builder()
.proxy(Proxy::http("http://localhost:8080")?)
.build()?;
let response = client.get("https://httpbin.org/get").send()?;
println!("{}", response.text()?);
Ok(())
}

这个例子中,我们使用 builder 方法创建了一个 HTTP 客户端,使用 proxy 方法设置了一个代理服务器,发送了一个 GET 请求。

下载文件#

use reqwest::blocking::Client;
use std::fs::File;
use std::io::copy;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new();
let mut response = client.get("https://httpbin.org/image/png").send()?;
let mut file = File::create("image.png")?;
copy(&mut response, &mut file)?;
Ok(())
}

这个例子中,我们发送了一个 GET 请求,下载了一个 PNG 图片,并保存到本地文件。

进阶用法#

异步操作#

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

这个例子中,我们使用 async/await 语法,在异步上下文中发送了一个 GET 请求。

自定义 SSL 证书#

use reqwest::blocking::Client;
use std::path::Path;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::builder()
.add_root_certificate(reqwest::Certificate::from_pem(
&std::fs::read(Path::new("cert.pem"))?,
))
.build()?;
let response = client.get("https://httpbin.org/get").send()?;
println!("{}", response.text()?);
Ok(())
}

这个例子中,我们使用 builder 方法创建了一个 HTTP 客户端,并使用 add_root_certificate 方法设置了一个自定义的 SSL 证书,发送了一个 GET 请求。

自定义连接池#

use reqwest::blocking::Client;
use std::time::Duration;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::builder()
.pool_idle_timeout(Duration::from_secs(30))
.build()?;
let response = client.get("https://httpbin.org/get").send()?;
println!("{}", response.text()?);
Ok(())
}

这个例子中,我们使用 builder 方法创建了一个 HTTP 客户端,并使用 pool_idle_timeout 方法设置了连接池的空闲超时时间,发送了一个 GET 请求。

自定义重试策略#

use reqwest::blocking::Client;
use std::time::Duration;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// reqwest 不内置 retry 方法,需手动实现或使用 reqwest-retry crate
let client = Client::builder()
.pool_idle_timeout(Duration::from_secs(30))
.build()?;
let mut attempts = 0;
let response = loop {
attempts += 1;
match client.get("https://httpbin.org/get").send() {
Ok(resp) => break resp,
Err(e) if attempts < 3 => {
eprintln!("Attempt {} failed: {}, retrying...", attempts, e);
std::thread::sleep(Duration::from_secs(attempts * 2));
}
Err(e) => return Err(e.into()),
}
};
println!("{}", response.text()?);
Ok(())
}

这个例子中,我们手动实现了重试策略,最多重试 3 次。Client::builder().retry() 方法不存在于 reqwest,推荐使用 reqwest-retry crate 或手动实现重试逻辑。

最佳实践#

使用连接池#

在高并发场景下,使用连接池可以提高 HTTP 客户端的性能和稳定性。可以使用 builder 方法设置连接池的大小和空闲超时时间。

use reqwest::blocking::Client;
use std::time::Duration;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::builder()
.pool_idle_timeout(Duration::from_secs(30))
.pool_max_idle_per_host(10)
.build()?;
let response = client.get("https://httpbin.org/get").send()?;
println!("{}", response.text()?);
Ok(())
}

处理错误#

在发送 HTTP 请求时,可能会出现各种错误,如网络错误,服务器错误等。可以使用 Result 类型来处理错误,或者使用?运算符简化代码。

use reqwest::blocking::Client;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new();
let response = client.get("https://httpbin.org/get").send()?;
if response.status().is_success() {
println!("{}", response.text()?);
} else {
println!("Error: {}", response.status());
}
Ok(())
}

使用代理#

在访问某些网站时,可能需要使用代理服务器。可以使用 builder 方法设置代理服务器的地址和端口。

use reqwest::blocking::Client;
use reqwest::Proxy;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::builder()
.proxy(Proxy::http("http://localhost:8080")?)
.build()?;
let response = client.get("https://httpbin.org/get").send()?;
println!("{}", response.text()?);
Ok(())
}

使用 JSON#

在发送 HTTP 请求时,经常需要使用 JSON 格式的请求体。可以使用 serde_json 库来创建 JSON 对象,并使用 json 方法设置请求体。

use reqwest::blocking::Client;
use serde_json::json;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new();
let data = json!({
"name": "Alice",
"age": 20
});
let response = client.post("https://httpbin.org/post")
.json(&data)
.send()?;
println!("{}", response.text()?);
Ok(())
}

使用表单#

在发送 HTTP 请求时,经常需要使用表单格式的请求体。可以使用 HashMap 来创建表单数据,并使用 form 方法设置请求体。

use reqwest::blocking::Client;
use std::collections::HashMap;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new();
let mut data = HashMap::new();
data.insert("name", "Alice");
data.insert("age", "20");
let response = client.post("https://httpbin.org/post")
.form(&data)
.send()?;
println!("{}", response.text()?);
Ok(())
}

结论#

在本教程中,我们介绍了 Rust 语言的 HTTP 客户端库 Reqwest 的基础用法和进阶用法,并提供了最佳实践和示例代码。使用 Reqwest 可以轻松地发送 HTTP 请求,并处理响应,满足各种应用场景的需求。

支持与分享

如果这篇文章对你有帮助,欢迎分享给更多人或赞助支持!

赞助
Rust语言从入门到精通系列 - Http客户端reqwest模块实战
https://tinyzzh.github.io/posts/2023-04-13-rust_lang_tutorial_220_http_reqwest/
作者
TinyZ Zzh
发布于
2023-04-13
许可协议
CC BY-NC-SA 4.0

评论区

Profile Image of the Author
TinyZ Zzh
专注于高并发服务器、网络游戏相关(Java、PHP、Unity3D、Unreal Engine等)技术,热爱游戏事业, 正在努力实现自我价值当中。
公告
欢迎来到我的博客!这是一则示例公告。
音乐
封面

音乐

暂未播放

0:00 0:00
暂无歌词
分类
标签
站点统计
文章
211
分类
38
标签
200
总字数
337,853
运行时长
0
最后活动
0 天前

文章目录