Reqwest: Rust HTTP客戶端函式庫

reqwestreqwest

Reqwest 是一個高階 HTTP 客戶端函式庫,它簡化了 HTTP 請求的處理流程,提供了許多常用功能:

  • 支援非同步與阻塞式 API
  • 處理各種類型的請求主體:純文字、JSON、URL編碼表單、多部分表單
  • 可自訂的重定向策略
  • HTTP 代理支援
  • 預設使用 TLS 加密
  • Cookie 管理

基本用法

發起 GET 請求

對於單一請求,可以使用 get 快捷方法:

let body = reqwest::get("https://www.rust-lang.org")
    .await?
    .text()
    .await?;

println!("body = {body:?}");

注意:若計劃執行多個請求,最好建立一個 Client 並重複使用,以利用連線池的優勢。

let client = reqwest::Client::new();
let res = client.get("https://www.rust-lang.org")
    .send()
    .await?;

發起 POST 請求

使用 body() 方法可以設定請求主體:

let client = reqwest::Client::new();
let res = client.post("http://httpbin.org/post")
    .body("要傳送的具體內容")
    .send()
    .await?;

表單資料

傳送表單資料是常見需求,可以使用任何可序列化為表單資料的類型:

// 這會傳送主體為 `foo=bar&baz=quux` 的 POST 請求
let params = [("foo", "bar"), ("baz", "quux")];
let client = reqwest::Client::new();
let res = client.post("http://httpbin.org/post")
    .form(¶ms)
    .send()
    .await?;

JSON 資料

透過 json 方法可輕鬆傳送 JSON 資料(需啟用 json 功能):

// 這會傳送主體為 `{"lang":"rust","body":"json"}` 的 POST 請求
let mut map = HashMap::new();
map.insert("lang", "rust");
map.insert("body", "json");

let client = reqwest::Client::new();
let res = client.post("http://httpbin.org/post")
    .json(&map)
    .send()
    .await?;

回應處理

可以多種方式處理回應:

let res = client.get("https://www.rust-lang.org").send().await?;

// 取得狀態碼
let status = res.status();

// 取得回應標頭
let content_type = res.headers().get("content-type").unwrap();

// 讀取回應主體為文字
let body = res.text().await?;

// 或解析為 JSON
let json: serde_json::Value = res.json().await?;

進階功能

重定向策略

預設情況下,客戶端會自動處理 HTTP 重定向,最多跟隨 10 次跳轉。可使用 ClientBuilder 自訂此行為:

let custom_client = reqwest::Client::builder()
    .redirect(reqwest::redirect::Policy::none()) // 停用重定向
    .build()?;

可透過 ClientBuilder 啟用會話 Cookie 的自動儲存與傳送:

let client = reqwest::Client::builder()
    .cookie_store(true)
    .build()?;

代理設定

系統代理預設啟用,會查找環境變數中的 HTTP 或 HTTPS 代理設定:

  • HTTP_PROXYhttp_proxy:HTTP 連線的代理
  • HTTPS_PROXYhttps_proxy:HTTPS 連線的代理
  • ALL_PROXYall_proxy:兩種連線的代理

也可透過程式碼明確設定代理:

let proxy = reqwest::Proxy::http("https://secure.example")?;
let client = reqwest::Client::builder()
    .proxy(proxy)
    .build()?;

// 或停用代理
let client = reqwest::Client::builder()
    .no_proxy()
    .build()?;

TLS 設定

客戶端預設使用 TLS 連線至 HTTPS 目標:

// 新增額外的伺服器憑證
let cert = reqwest::Certificate::from_pem(&cert_bytes)?;
let client = reqwest::Client::builder()
    .add_root_certificate(cert)
    .build()?;

// 設定客戶端憑證
let identity = reqwest::Identity::from_pkcs12_der(&pkcs12_der, "password")?;
let client = reqwest::Client::builder()
    .identity(identity)
    .build()?;

逾時設定

可為請求設定逾時時間:

let client = reqwest::Client::builder()
    .timeout(std::time::Duration::from_secs(10))
    .build()?;

可選功能

Reqwest 提供多種可選功能,可透過 Cargo 功能啟用或停用:

  • http2(預設啟用):支援 HTTP/2
  • default-tls(預設啟用):提供 HTTPS 的 TLS 支援
  • rustls-tls:使用 rustls 提供 TLS 功能
  • blocking:提供阻塞式客戶端 API
  • json:提供 JSON 序列化與反序列化功能
  • multipart:提供多部分表單功能
  • cookies:提供 cookie 會話支援
  • gzipbrotlideflatezstd:支援各種回應主體解壓縮
  • socks:提供 SOCKS5 代理支援

阻塞式 API

當不需要非同步操作時,可使用阻塞式 API(需啟用 blocking 功能):

let body = reqwest::blocking::get("https://www.rust-lang.org")?.text()?;

let client = reqwest::blocking::Client::new();
let res = client.post("http://httpbin.org/post")
    .json(&map)
    .send()?;