【Rust】reqwest の基本と使い方を分かりやすく解説

Rust で HTTP 通信を行うためのクレートである reqwest の基本的な使い方について、初心者にも分かりやすく解説します。
reqwest クレートの概要
reqwest とは
reqwest は、Rust で HTTP 通信を行うための代表的なクレートです。GET や POST などの HTTP リクエストを簡潔なコードで記述でき、JSON の送受信、認証ヘッダーの付与、タイムアウト設定なども柔軟に対応しています。
Rust の標準ライブラリには、HTTP クライアント機能は含まれていないため、Web API との通信が必要な場面では、reqwest がデファクトスタンダードとして広く使用されています。
この記事では、reqwest の基本的な使い方を紹介します。
非同期モードと同期モード
reqwest には、非同期モードと同期モードの 2 種類があります。reqwest は、非同期処理ランタイムの tokio をベースに構築されており、デフォルトは非同期モードです。
- 非同期モード(デフォルト):
async/awaitを使用して非同期でリクエストを送信します。非同期処理ランタイムであるtokioが必要です。 - 同期モード:
reqwest::blockingモジュールを使うことで、通常の同期コードとして HTTP リクエストを書くことができます。使用する場合には、blocking feature を有効にする必要があります。
この記事では、実務上よく使われる非同期モードを中心に解説します。同期モード(reqwest::blocking)については、後半で簡単に触れます。
reqwest を使用した HTTP 通信の基本
reqwest の導入方法
reqwest は、他のクレートと同様に cargo add または Cargo.toml に追記することで利用できます。
cargo add で追加する場合
cargo add reqwest --features json,query cargo add tokio --features full
Cargo.toml に追記する場合
[dependencies]
reqwest = { version = "0.13", features = ["json", "query"] }
tokio = { version = "1", features = ["full"] }feature について
reqwest の json feature を有効にすることで、json メソッドが使えるようになります。これにより、リクエストボディへの JSON 埋め込みや、レスポンスの JSON デシリアライズを簡単に行うことができます。JSON を扱う場合には、必ず指定するようにしましょう。また、以降で使用する query メソッドも使えるように query feature も有効にします。
tokio の full feature は、tokio が提供するすべての機能を有効にしておきます。
導入時には crates.io の reqwest や tokio のページを確認してください。なお、実際にインストールされたバージョンは Cargo.lock ファイルで確認できます。
テスト用サービス httpbin.org
HTTP リクエストとレスポンスをテストする
HTTP リクエストとレスポンスのテストをするためには、API を提供するサーバーが必要になります。今回は「httpbin.org」を使用します。
httpbin.org は、HTTP リクエストとレスポンスのテストに使用される人気のオンラインサービスで、開発者が HTTP リクエストを送信し、レスポンスを確認することができます。
httpbin.org は、WebAPI 開発や HTTP クライアントのライブラリ、フレームワークのテストなどに広く使用されています。
Docker 環境の利用
httpbin.org は、通信タイミングによってサービスが不安定なことがあります。httpbin.org のサービスは、Docker 環境が用意されているため、Docker 環境が手元にある場合には、以下のコマンドでローカル実行してテストする方が安定的に動作の確認が可能です。
docker run --rm -p 8080:80 kennethreitz/httpbin
上記コマンドを実行すると「kennethreitz/httpbin」というコンテナ環境をインストールし、起動します。--rm オプションは、終了時にコンテナを削除するコマンドで、-p 8080:80 はポートの接続設定です。ローカル環境からは 8080 ポートを使用してコンテナにアクセスします。
なお、httpbin.org にアクセスする場合は、https で SSL可能ですが、ローカルの Docker 環境は SSL 通信は対応していないので http でアクセスする必要があります。
以降のサンプルコードでは、https://httpbin.org への URL を記載しています。ローカルの Docker 環境を使う場合は http://localhost:8080 に切り替えて試してください。
各 HTTP メソッドでリクエストを送信する
(GET / POST/ PUT / DELETE)
基本的な使い方の流れ
reqwest を用いて HTTP 通信をする際の基本的な流れは以下の通りです。
ClientBuilderを生成して、タイムアウトなどの通信の設定をする。ClientBuilderからClientを生成する。RequestBuilderを生成し、パラメータなどの設定をする。- リクエストを送信 (
send) し、レスポンスを取得する。 - 取得したレスポンスからヘッダーやボディなど必要な情報を取り出す。
以降では、上記の流れで各 HTTP メソッドを使用する例を順番に紹介します。
GET リクエストでレスポンスを取得する
基本的な使い方
基本的な GET リクエストを送ってレスポンスを取得する例から見ていきましょう。
use std::error::Error;
use std::time::Duration;
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
// httpbin.org から取得する
let url = "https://httpbin.org/get";
// Docker を使用する場合は、以下のように URL を変更してください
// let url = "http://localhost:8080/get";
// ClientBuilder でタイムアウトなどを設定する
let client_builder = reqwest::Client::builder().timeout(Duration::from_secs(10));
// ClientBuilder から Client を作成する
let client = client_builder.build()?;
// RequestBuilder を作成する
let request_builder = client.get(url);
// レスポンスを取得する
let response = request_builder.send().await?;
// ステータスコードを取得する
let status = response.status();
println!("ステータスコード:\n{status}\n");
// レスポンスボディを文字列として取得する
let text = response.text().await?;
println!("応答の文字列形式:\n{text}");
Ok(())
}【実行結果】
ステータスコード:
200 OK
応答の文字列形式:
{
"args": {},
"headers": {
"Accept": "*/*",
"Host": "httpbin.org",
"X-Amzn-Trace-Id": "Root=1-6a49b680-6c650d0050fcf1c707d6e742"
},
"origin": "xxx.xxx.xxx.xxx",
"url": "https://httpbin.org/get"
}#[tokio::main] は、main 関数を非同期関数として実行するためのものです。reqwest の非同期モードでは、tokio のランタイムが必要なため、この指定が必要です。
まず、reqwest::Client::builder() で ClientBuilder を生成し、timeout() で通信タイムアウトを設定しています。
次に、client.get(url) で、RequestBuilder を生成し、send().await でリクエストを送信します。このとき、await で非同期処理の完了を待ち、? 演算子でエラーを呼び出し元に伝播しています。
レスポンスからは、status() でステータスコードを取得でき、ボディの文字列を取得する際には、text().await を使用します。text() は非同期処理のため、await が必要な点に注意してください。
クエリパラメータを指定する
GET リクエストを送る際に、検索の条件となるクエリパラメータを指定する場合には、query メソッドを使用します。
use std::error::Error;
use std::time::Duration;
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
...(Client 作成までは同様なので省略)...
// RequestBuilder を作成する
// query() でクエリパラメータを付与することができる
let queries = [("key1", "value1"), ("key2", "value2")];
let request_builder = client.get(url).query(&queries);
// レスポンスを取得する
let response = request_builder.send().await?;
...(ステータスコード表示とボディの表示は同様なので省略)...
}【実行結果】
ステータスコード:
200 OK
応答の文字列形式:
{
"args": {
"key1": "value1",
"key2": "value2"
},
"headers": {
"Accept": "*/*",
"Host": "httpbin.org",
"X-Amzn-Trace-Id": "Root=1-6a49b7d7-169234f062f0d8bb46cea5c2"
},
"origin": "xxx.xxx.xxx.xxx",
"url": "https://httpbin.org/get?key1=value1&key2=value2"
}query メソッドにキーと値を持った配列を渡すことで、クエリパラメータを設定できます。具体的な URL としては、https://httpbin.org/get?key1=value1&key2=value2 のように送信されることになります。
ヘッダーを扱う
リクエストの際にはヘッダー情報を指定する場合や、レスポンスのヘッダーを確認することがよくあります。ヘッダーの扱いについても以下で確認しましょう。
use std::error::Error;
use std::time::Duration;
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
...(Client 作成までは同様なので省略)...
// RequestBuilder を作成する
// header() でリクエストヘッダーを付与することができる
// API キーを送信する場合によく使われる例
let request_builder = client.get(url).header("X-API-Key", "sample-api-key");
// レスポンスを取得する
let response = request_builder.send().await?;
// ステータスコードを取得する
let status = response.status();
println!("ステータスコード:\n{status}\n");
// ヘッダーを取得する
let headers = response.headers();
println!("ヘッダー:\n{headers:?}\n");
// ヘッダーから特定の項目だけを取り出す例
// ヘッダーは HeaderMap 型で取得されるので、get() メソッドで取り出す
// 値の型は HeaderValue なので、文字列に変換する必要がある
let content_type = headers
.get("content-type")
.ok_or("content-type ヘッダーが見つかりません")?
.to_str()?;
println!("content-type ヘッダー: {content_type}\n");
// レスポンスボディを文字列として取得する
let text = response.text().await?;
println!("応答の文字列形式:\n{text}");
Ok(())
}【実行結果】
ステータスコード:
200 OK
ヘッダー:
{"date": "Sun, 05 Jul 2026 02:06:48 GMT", "content-type": "application/json", "content-length": "257", "server": "gunicorn/19.9.0", "access-control-allow-origin": "*", "access-control-allow-credentials": "true"}
content-type ヘッダー: application/json
応答の文字列形式:
{
"args": {},
"headers": {
"Accept": "*/*",
"Host": "httpbin.org",
"X-Amzn-Trace-Id": "Root=1-6a49bc38-646f78d43467315669dd0b4a",
"X-Api-Key": "sample-api-key"
},
"origin": "xxx.xxx.xxx.xxx",
"url": "https://httpbin.org/get"
}リクエストのヘッダーに固有のヘッダを付与したい場合には、RequestBuilder で、header メソッドを使用します。例の「header("X-API-Key", "sample-api-key")」のような指定は、外部サービスの REST API を使用する際に固有の認証キーを使う際によく利用されます。
レスポンスのヘッダー情報は、headers メソッドで全体を取得できます。ヘッダーは、HeaderMap 型であり、特定の項目を取り出す際は、get() でアクセスします。取得される値は HeaderValue 型のため、最後に to_str で文字列に変換します。
JSON レスポンスを構造体にデシリアライズする
Web API では JSON 形式のレスポンスを受け取るケースが多くあります。reqwest では serde と組み合わせることで、JSON レスポンスを構造体に直接デシリアライズできます。デシリアライズするためには serde が必要です。cargo addで追加しておいてください。
cargo add serde --features derive
use serde::Deserialize;
use std::collections::HashMap;
use std::error::Error;
use std::time::Duration;
// url と headers だけを保持する構造体
#[derive(Debug, Deserialize)]
struct HttpBinResponse {
url: String,
headers: HashMap<String, String>,
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
...(Client 作成までは同様なので省略)...
// RequestBuilder を作成する
let request_builder = client.get(url);
// レスポンスを取得する
let response = request_builder.send().await?;
// json() で構造体にデシリアライズする
let data: HttpBinResponse = response.json().await?;
// url と headers を取り出す
println!("url: {}", data.url);
println!("headers: {:?}", data.headers);
Ok(())
}【実行結果】
url: https://httpbin.org/get
headers: {"X-Amzn-Trace-Id": "Root=1-6a498cbb-25fe1cde73cbb10827f0d817", "Accept": "*/*", "Host": "httpbin.org"}json().await で、レスポンスボディを指定した型に直接デシリアライズできます。受け取る変数には「let data: HttpBinResponse」のように型を明示する必要があります。また、JSON で取り込む構造体は、#[derive(Deserialize)]を付けて定義する必要があります。
JSON のフィールドと構造体のフィールドが一致しない場合や、型が合わない場合にはエラーとなります。存在しない場合があるフィールドは Option<T> にしておくと安全です。
POST リクエストで JSON を送信する
JSON データを含めて POST リクエストを送信する例を見てみましょう。POST でデータを登録する場合には、対象サービスのエンドポイントが用意されます。
今回は、https://httpbin.org/anything/users というエンドポイントがユーザー登録のためのエンドポイントとして例を紹介します。なお、httpbin.org で /anything や /anything/<任意パス> は、HTTPメソッドを問わず、リクエスト内容をそのまま返却するようなエンドポイントです。今回は、users というユーザー登録のエンドポイント例の代替として使用します。
use std::error::Error;
use std::time::Duration;
use serde::Serialize;
// リクエストボディとして送信するデータ
// user_id はサーバー側で採番される想定とする
#[derive(Serialize)]
struct User {
name: String,
age: u32,
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
// httpbin.org へ送信する
// ユーザー登録エンドポイントを呼び出す
let url = "https://httpbin.org/anything/users";
// Docker を使用する場合は、以下のように URL を変更してください
// let url = "http://localhost:8080/anything/users";
// ClientBuilder でタイムアウトなどを設定する
let client_builder = reqwest::Client::builder().timeout(Duration::from_secs(10));
// ClientBuilder から Client を作成する
let client = client_builder.build()?;
// 送信するデータ
let user = User {
name: "Taro".to_string(),
age: 30,
};
// RequestBuilder を作成する
// json() でリクエストボディを JSON として送信する
let request_builder = client.post(url).json(&user);
// レスポンスを取得する
let response = request_builder.send().await?;
// ステータスコードを取得する
let status = response.status();
println!("ステータスコード:\n{status}\n");
// レスポンスボディを文字列として取得する
let text = response.text().await?;
println!("応答の文字列形式:\n{text}");
Ok(())
}【実行結果】
ステータスコード:
200 OK
応答の文字列形式:
{
"args": {},
"data": "{\"name\":\"Taro\",\"age\":30}",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Content-Length": "24",
"Content-Type": "application/json",
"Host": "httpbin.org",
"X-Amzn-Trace-Id": "Root=1-6a49c912-2d1d37541f89dcbd32a31524"
},
"json": {
"age": 30,
"name": "Taro"
},
"method": "POST",
"origin": "xxx.xxx.xx.xxx",
"url": "https://httpbin.org/anything/users"
}client.post(url) で POST リクエストの RequestBuilder を作成し、json(&user) で送信したい構造体のデータを設定します。
送信するデータの構造体には #[derive(Serialize)] を付与しておく必要があります。なお、json() は内部で Content-Type: application/json ヘッダーも自動付与してくれます。
PUT リクエストでデータを更新する
PUT リクエストについても考えましょう。今回の例では、既に user_id が POST により登録されており、https://httpbin.org/anything/users/u1001 というユーザー ID のエンドポイントを PUT で呼び出すと考えます。
REST API では、このようにエンドポイントで対象となる ID をパスパラメータとして指定できるように作られることが一般的です。
use std::error::Error;
use std::time::Duration;
use serde::Serialize;
// リクエストボディとして送信するデータ
// user_id は URL のパスパラメータで指定するため、ボディには含めない
#[derive(Serialize)]
struct User {
name: String,
age: u32,
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
// 更新対象の user_id
let user_id = "u1001";
// httpbin.org へ送信する
// user_id をパスパラメータとして URL に含める
let url = format!("https://httpbin.org/anything/users/{user_id}");
// Docker を使用する場合は、以下のように URL を変更してください
// let url = format!("http://localhost:8080/anything/users/{user_id}");
...(Client 作成までは同様なので省略)...
// 更新後のデータ
let user = User {
name: "Miki".to_string(),
age: 25,
};
// RequestBuilder を作成する
// put() で PUT リクエストを送信する
let request_builder = client.put(url).json(&user);
// レスポンスを取得する
let response = request_builder.send().await?;
// ステータスコードを取得する
let status = response.status();
println!("ステータスコード:\n{status}\n");
// レスポンスボディを文字列として取得する
let text = response.text().await?;
println!("応答の文字列形式:\n{text}");
Ok(())
}【実行結果】
ステータスコード:
200 OK
応答の文字列形式:
{
"args": {},
"data": "{\"name\":\"Miki\",\"age\":25}",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Content-Length": "24",
"Content-Type": "application/json",
"Host": "httpbin.org",
"X-Amzn-Trace-Id": "Root=1-6a49c11f-39b3368462de6e1f2244052c"
},
"json": {
"age": 25,
"name": "Miki"
},
"method": "PUT",
"origin": "xxx.xxx.xxx.xxx",
"url": "https://httpbin.org/anything/users/u1001"
}対象とする ID 情報は、例のように format! を用いて埋め込むのが簡単です。それ以降の処理の流れは、post が put に変わるだけで同様の流れとなります。
DELETE リクエストでデータを削除する
DELETE リクエストも、PUT と同様に https://httpbin.org/anything/users/u1001 に対して DELETE のリクエストを送信する例を考えます。
use std::error::Error;
use std::time::Duration;
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
// 削除対象の user_id
let user_id = "u1001";
// httpbin.org へ送信する
// user_id をパスパラメータとして URL に含める
let url = format!("https://httpbin.org/anything/users/{user_id}");
// Docker を使用する場合は、以下のように URL を変更してください
// let url = format!("http://localhost:8080/anything/users/{user_id}");
...(Client 作成までは同様なので省略)...
// RequestBuilder を作成する
// delete() で DELETE リクエストを送信する
let request_builder = client.delete(url);
// レスポンスを取得する
let response = request_builder.send().await?;
// ステータスコードを取得する
let status = response.status();
println!("ステータスコード:\n{status}\n");
// レスポンスボディを文字列として取得する
let text = response.text().await?;
println!("応答の文字列形式:\n{text}");
Ok(())
}【実行結果】
ステータスコード:
200 OK
応答の文字列形式:
{
"args": {},
"data": "",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Host": "httpbin.org",
"X-Amzn-Trace-Id": "Root=1-6a49c102-51e1f4260751237d2a3ea3c7"
},
"json": null,
"method": "DELETE",
"origin": "xxx.xxx.xxx.xxx",
"url": "https://httpbin.org/anything/users/u1001"
}DELETE の場合は、対象が識別できればいいので、エンドポイントを指定して delete メソッドを呼び出しているだけになります。プログラムの構成としては、PUT と同様です。
エラー情報に対処する
各 HTTP メソッドの使い方を見てきました。これまでの例は、成功ステータスの例のみでしたが、実開発では、エラーステータスコードの場合、適切な処理が必要です。4xx、5xx 番はエラーとして扱いますが、これまで紹介したメソッドは、レスポンスが返ってくれば 4xx や 5xx でも Ok 扱いとなります。
そのため、エラーステータスを判断して処理をしたい場合は、レスポンスの error_for_status メソッドを使用します。このメソッドは、4xx、5xx の場合に、Err を返すため、? 演算子と組み合わせるなど状況に応じて適切にエラー処理ができます。
httpbin.org には、特定のエラーコードを返却するエンドポイントが用意されているので、今回は、ステータスコード 400 が返ってくる場合の対処例を紹介します。
use std::error::Error;
use std::time::Duration;
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
// httpbin.org から取得する
let url = "https://httpbin.org/status/400";
// Docker を使用する場合は、以下のように URL を変更してください
// let url = "http://localhost:8080/status/400";
// ClientBuilder でタイムアウトなどを設定する
let client_builder = reqwest::Client::builder().timeout(Duration::from_secs(10));
// ClientBuilder から Client を作成する
let client = client_builder.build()?;
// ケース1: HTTP レベルのエラー(ステータスコードが 4xx や 5xx)
// 通信自体は成功しているため、send() は Ok(Response) を返す
let response = client.get(url).send().await?;
println!("ステータスコード: {}\n", response.status());
// error_for_status() を使うと、4xx・5xx のステータスコードを Err に変換できる
match response.error_for_status() {
Ok(response) => println!("成功として扱われました: {}", response.status()),
Err(error) => println!("error_for_status() でエラーになりました: {error}"),
}
println!();
// ケース2: 通信レベルのエラー
// 存在しないホスト名のため、DNS 解決に失敗して send() 自体が Err を返す
let invalid_url = "https://this-host-does-not-exist.com";
match client.get(invalid_url).send().await {
Ok(response) => println!("ステータスコード: {}", response.status()),
Err(error) => println!("send() でエラーになりました: {error}"),
}
Ok(())
}【実行結果】 ステータスコード: 400 Bad Request error_for_status() でエラーになりました: HTTP status client error (400 Bad Request) for url (https://httpbin.org/status/400) send() でエラーになりました: error sending request for url (https://this-host-does-not-exist.com/)
ケース1 は、通信は通っているものの適切なリクエストの仕方ではなかったため、400 番のレスポンスがあった場合です。一方で、ケース2 の方は、そもそも通信レベルのエラーの場合です。例では存在しない URL へアクセスしようとして通信が返ってきません。この時は、send の時点で Err が返ってきます。どちらのケースのエラーであるのかを判断できるようにコーディングするようにしましょう。
汎用メソッド request を使用する
これまで、get、post、put、delete と各 HTTP メソッドごとの専用メソッドを使ってきました。reqwest には、HTTP メソッドを動的に指定できる request という汎用メソッドも用意されています。
use std::error::Error;
use std::time::Duration;
use reqwest::Method;
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
// ClientBuilder でタイムアウトなどを設定する
let client_builder = reqwest::Client::builder().timeout(Duration::from_secs(10));
// ClientBuilder から Client を作成する
let client = client_builder.build()?;
// 対象の user_id
let user_id = "u1001";
// request() を使うと、get()・post()・put()・delete() のような専用メソッドの代わりに、
// Method を指定して同じ内容のリクエストを送信できる
let requests = [
(
"GET",
Method::GET,
"https://httpbin.org/anything/users".to_string(),
),
(
"POST",
Method::POST,
"https://httpbin.org/anything/users".to_string(),
),
(
"PUT",
Method::PUT,
format!("https://httpbin.org/anything/users/{user_id}"),
),
(
"DELETE",
Method::DELETE,
format!("https://httpbin.org/anything/users/{user_id}"),
),
];
for (label, method, url) in requests {
// RequestBuilder を作成する
let request_builder = client.request(method, url);
// レスポンスを取得する
let response = request_builder.send().await?;
// ステータスコードを取得する
let status = response.status();
println!("[{label}] {status}");
}
Ok(())
}【実行結果】 [GET] 200 OK [POST] 200 OK [PUT] 200 OK [DELETE] 200 OK
request では、例えば、GET であれば、client.request(Method::GET, url) のように reqwest::Method 型を指定することで HTTP メソッドを切り替えます。client.get() などの個別メソッドは、内部的にはこの client.request() を呼び出すラッパーになっています。
呼び出されるメソッドが明確な場合は、各専用メソッドを用いる方が可読性の観点で優れています。一方で、ライブラリなどで動的に呼び出すメソッドを変更したい場合には、request を使って実装するのがおすすめです。
同期通信 reqwest::blocking
この記事の冒頭で説明した通り、reqwest は、非同期モードがデフォルトになっています。同期的に使用したい場合には、reqwest::blocking を使用します。 blocking はデフォルトでは無効なので「cargo add reqwest --features json,query,blocking」のように blocking feature を有効にするようにしてください。
use std::error::Error;
use std::time::Duration;
// blocking::Client を使うと、async/await を使わずに同期的に通信できる
// tokio::main は不要で、通常の fn main で実行できる
fn main() -> Result<(), Box<dyn Error>> {
// httpbin.org から取得する
let url = "https://httpbin.org/get";
// Docker を使用する場合は、以下のように URL を変更してください
// let url = "http://localhost:8080/get";
// ClientBuilder でタイムアウトなどを設定する
let client_builder = reqwest::blocking::Client::builder().timeout(Duration::from_secs(10));
// ClientBuilder から Client を作成する
let client = client_builder.build()?;
// 同じ Client で複数回リクエストを送る
for count in 1..=3 {
// RequestBuilder を作成する
let request_builder = client.get(url);
// レスポンスを取得する(await が不要)
let response = request_builder.send()?;
// ステータスコードを取得する
let status = response.status();
println!("{count}回目 ステータスコード: {status}");
}
Ok(())
}【実行結果】 1回目 ステータスコード: 200 OK 2回目 ステータスコード: 200 OK 3回目 ステータスコード: 200 OK
非同期との違いは、まず、main 関数が同期関数となっている点です。#[tokio::main] の付いた関数の中で reqwest::blocking を使うと実行時に panic となるので、非同期との併用は不可である点は注意してください。
また、使い方では、ClientBuilder 生成で reqwest::blocking::Client::builder() を使用する点が異なります。それ以外の使い方はほとんど同様ですが、同期実行であるため、send の際に await は不要となります。
まとめ
Rust で HTTP 通信を行うためのクレートである reqwest の基本的な使い方について、解説しました。
GET・POST・PUT・DELETE といった基本的な HTTP メソッドの使い方から、クエリパラメータやヘッダーの指定、JSON のシリアライズ・デシリアライズ、エラー処理の考え方まで、実務でよく使う内容を中心に紹介しました。
また、汎用メソッドの request や、同期的に扱える reqwest::blocking についても紹介しました。基本の使い方をしっかり押さえておくことで、外部 API との連携など、様々な場面で活用できるようになります。ぜひ、基本的な使い方を理解してください。
上記で紹介しているソースコードについては GitHub にて公開しています。参考にしていただければと思います。

