Reqwest is a powerful, user-friendly, and highly ergonomic HTTP client for the Rust programming language. It is primarily designed to work asynchronously, leveraging Rust's `async/await` syntax and the `tokio` runtime, making it ideal for high-performance network applications.
Key Features and Capabilities:
1. Asynchronous Operations: Built on top of `tokio` and `hyper`, `reqwest` provides a non-blocking API for making HTTP requests, allowing your application to perform other tasks while waiting for network responses.
2. Ergonomic API: It offers a fluent and intuitive API for common HTTP operations (GET, POST, PUT, DELETE, etc.), making it easy to construct complex requests.
3. Automatic Serialization/Deserialization: Seamlessly handles sending JSON or form data in request bodies and deserializing JSON responses directly into Rust structs using the `serde` crate. This significantly reduces boilerplate code.
4. Custom Headers and Query Parameters: Provides straightforward methods for adding custom HTTP headers, setting query parameters, and configuring various aspects of a request.
5. TLS/SSL Support: Automatically handles HTTPS requests using `native-tls` (default) or `rustls` feature flags, ensuring secure communication.
6. Connection Pooling: The `reqwest::Client` struct manages connections efficiently, reusing them for multiple requests to the same host, which improves performance by reducing overhead.
7. Redirects and Proxies: Supports automatic following of redirects and configuration for HTTP proxies.
8. Error Handling: Integrates with Rust's robust error handling mechanisms, returning `Result` types for network operations.
9. Blocking Client: While primarily async, `reqwest` also offers a `reqwest::blocking::Client` for synchronous (blocking) operations, suitable for simpler scripts or environments where `async/await` isn't desired.
How it works:
`reqwest` relies on several key crates:
* `tokio`: Provides the asynchronous runtime for executing non-blocking operations.
* `hyper`: A fast, low-level HTTP implementation that `reqwest` builds upon.
* `serde`: Used for serializing Rust data structures into formats like JSON or form data, and deserializing responses back into Rust structs.
To use `reqwest`, you typically create an instance of `reqwest::Client` (or `reqwest::blocking::Client`), which can then be used to build and send various HTTP requests. The client handles underlying connection management and configuration.
Use Cases:
* Consuming RESTful APIs.
* Web scraping (with appropriate ethical considerations).
* Building microservices that communicate with each other.
* Any application requiring outbound HTTP requests.
Example Code
```rust
// --- Cargo.toml ---
// Add the following dependencies to your Cargo.toml file:
// [dependencies]
// reqwest = { version = "0.12", features = ["json"] }
// tokio = { version = "1", features = ["full"] } # Use "full" or specify features like ["macros", "rt-multi-thread"]
// serde = { version = "1", features = ["derive"] }
// --- main.rs ---
use reqwest;
use serde::{Deserialize, Serialize};
use std::error::Error;
// Define a struct to deserialize the JSON response from the API into.
// The `Deserialize` derive macro from `serde` makes this easy.
#[derive(Debug, Deserialize, Serialize)]
struct Post {
#[serde(rename = "userId")] // Map `userId` from JSON to `user_id` in Rust
user_id: u32,
id: u32,
title: String,
body: String,
}
// The `#[tokio::main]` attribute makes the `main` function asynchronous
// and sets up the Tokio runtime.
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
// Create a new reqwest client. It's recommended to reuse a single client
// for multiple requests to benefit from connection pooling.
let client = reqwest::Client::new();
println!("\n--- Making a GET request ---");
// Make an asynchronous GET request to a public JSON placeholder API.
let get_response = client
.get("https://jsonplaceholder.typicode.com/posts/1")
.send()
.await?;
// Check if the request was successful (status code 2xx).
if get_response.status().is_success() {
// Deserialize the JSON response body directly into our `Post` struct.
let post: Post = get_response.json().await?;
println!("Successfully fetched post:\n{:#?}", post);
} else {
// Handle non-successful responses.
eprintln!("GET request failed with status: {}", get_response.status());
eprintln!("Response body: {}", get_response.text().await?);
}
println!("\n--- Making a POST request ---");
// Example of creating a new post using a POST request.
let new_post = Post {
user_id: 1,
id: 0, // ID is typically assigned by the server, 0 for new posts
title: "Rust Reqwest Example".to_string(),
body: "This is a sample post created using reqwest in Rust.".to_string(),
};
let post_response = client
.post("https://jsonplaceholder.typicode.com/posts")
.json(&new_post) // Serialize our `new_post` struct into JSON for the request body.
.send()
.await?;
if post_response.status().is_success() {
let created_post: Post = post_response.json().await?;
println!("Successfully created post (server usually returns the created resource):\n{:#?}", created_post);
} else {
eprintln!("POST request failed with status: {}", post_response.status());
eprintln!("Response body: {}", post_response.text().await?);
}
Ok(())
}
```








reqwest