Loading page…
Rust walkthroughs
Loading page…
Reqwest is a simple, higher-level HTTP client for Rust. It provides a convenient API for making HTTP requests, handling responses, and working with various content types. Built on top of hyper, it offers both blocking and async APIs.
Key concepts:
When to use Reqwest:
When NOT to use Reqwest:
axum or hyper directly)hyper directly)use reqwest::blocking::get;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Simple GET request
let response = get("https://httpbin.org/get")?;
println!("Status: {}", response.status());
println!("Headers:\n{:#?}", response.headers());
// Get body as text
let body = response.text()?;
println!("Body:\n{}", body);
Ok(())
}use reqwest::Client;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let body = reqwest::get("https://httpbin.org/get").await?.text().await?;
println!("Body: {}", body);
Ok(())
}use reqwest::blocking::Client;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create a reusable client
let client = Client::new();
// Make multiple requests with same client
let resp1 = client.get("https://httpbin.org/get").send()?;
let resp2 = client.get("https://httpbin.org/ip").send()?;
println!("Response 1: {}", resp1.status());
println!("Response 2: {}", resp2.status());
Ok(())
}use reqwest::blocking::Client;
use serde_json::json;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new();
let body = json!({
"name": "Alice",
"email": "alice@example.com"
});
let response = client
.post("https://httpbin.org/post")
.json(&body)
.send()?;
println!("Status: {}", response.status());
println!("Response: {}", response.text()?);
Ok(())
}use reqwest::blocking::Client;
use std::collections::HashMap;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new();
let mut form = HashMap::new();
form.insert("username", "alice");
form.insert("password", "secret");
let response = client
.post("https://httpbin.org/post")
.form(&form)
.send()?;
println!("Response: {}", response.text()?);
Ok(())
}use reqwest::blocking::Client;
use reqwest::header::{HeaderMap, HeaderValue, USER_AGENT, CONTENT_TYPE, AUTHORIZATION};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new();
// Build headers
let mut headers = HeaderMap::new();
headers.insert(USER_AGENT, HeaderValue::from_static("MyApp/1.0"));
headers.insert(CONTENT_TYPE, HeaderValue::from_static("application/json"));
headers.insert(AUTHORIZATION, HeaderValue::from_static("Bearer token123"));
let response = client
.get("https://httpbin.org/headers")
.headers(headers)
.send()?;
println!("Response: {}", response.text()?);
Ok(())
}use reqwest::blocking::Client;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new();
let response = client
.get("https://httpbin.org/get")
.query(&[
("page", "1"),
("limit", "10"),
("sort", "created"),
])
.send()?;
println!("URL: {:?}", response.url());
println!("Response: {}", response.text()?);
Ok(())
}
### Handling JSON Responses
```rust
use reqwest::blocking::Client;
use serde::Deserialize;
#[derive(Deserialize, Debug)]
struct IpResponse {
origin: String,
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new();
// Deserialize JSON directly
let ip: IpResponse = client
.get("https://httpbin.org/ip")
.send()?\
.json()?;
println!("IP: {}", ip.origin);
Ok(())
}use reqwest::blocking::Client;
use reqwest::StatusCode;
fn fetch_url(url: &str) -> Result<String, Box<dyn std::error::Error>> {
let client = Client::new();
let response = client.get(url).send()?;
match response.status() {
StatusCode::OK => Ok(response.text()?),
StatusCode::NOT_FOUND => Err("Not found".into()),
StatusCode::INTERNAL_SERVER_ERROR => Err("Server error".into()),
status => Err(format!("Unexpected status: {}", status).into()),
}
}
fn main() {
match fetch_url("https://httpbin.org/get") {
Ok(body) => println!("Success: {} bytes", body.len()),
Err(e) => eprintln!("Error: {}", e),
}
}use reqwest::blocking::Client;
use std::time::Duration;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::builder()
.timeout(Duration::from_secs(10))
.connect_timeout(Duration::from_secs(5))
.build()?;
let response = client
.get("https://httpbin.org/delay/2")
.send()?;
println!("Status: {}", response.status());
Ok(())
}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 dest = File::create("downloaded.png")?;
copy(&mut response, &mut dest)?;
println!("Downloaded successfully");
Ok(())
}use reqwest::blocking::Client;
use std::fs::File;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new();
let file = File::open("example.txt")?;
let response = client
.post("https://httpbin.org/post")
.body(file)
.send()?;
println!("Response: {}", response.status());
Ok(())
}use reqwest::blocking::Client;
use reqwest::multipart;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new();
let form = multipart::Form::new()
.text("name", "Alice")
.file("document", "example.txt")?;
let response = client
.post("https://httpbin.org/post")
.multipart(form)
.send()?;
println!("Response: {}", response.status());
Ok(())
}use reqwest::blocking::Client;
use reqwest::cookie::Jar;
use std::sync::Arc;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let cookie_store = Arc::new(Jar::default());
let client = Client::builder()
.cookie_provider(cookie_store)
.build()?;
// First request sets cookie
let resp1 = client.get("https://httpbin.org/cookies/set?session=abc123").send()?;
println!("Set cookies: {:?}", resp1.cookies().collect::<Vec<_>>());
// Second request sends cookie
let resp2 = client.get("https://httpbin.org/cookies").send()?;
println!("Response: {}", resp2.text()?);
Ok(())
}use reqwest::blocking::Client;
use reqwest::redirect;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Follow up to 10 redirects (default)
let client = Client::builder()
.redirect(redirect::Policy::limited(10))
.build()?;
// Or disable redirects
let no_redirect_client = Client::builder()
.redirect(redirect::Policy::none())
.build()?;
let response = client.get("https://httpbin.org/redirect/2").send()?;
println!("Final URL: {}", response.url());
Ok(())
}use reqwest::blocking::Client;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new();
let response = client
.get("https://httpbin.org/basic-auth/user/pass")
.basic_auth("user", Some("pass"))
.send()?;
println!("Status: {}", response.status());
Ok(())
}use reqwest::blocking::Client;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new();
let response = client
.get("https://httpbin.org/bearer")
.bearer_auth("my-token")
.send()?;
println!("Status: {}", response.status());
Ok(())
}use reqwest::blocking::Client;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Accept invalid certificates (for testing only!)
let client = Client::builder()
.danger_accept_invalid_certs(true)
.build()?;
// For production, add custom root certificates:
// let cert = reqwest::Certificate::from_pem(include_bytes!("cert.pem"))?;
// let client = Client::builder()
// .add_root_certificate(cert)
// .build()?;
let response = client.get("https://example.com").send()?;
println!("Status: {}", response.status());
Ok(())
}use reqwest::blocking::Client;
use reqwest::Proxy;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let proxy = Proxy::all("http://proxy.example.com:8080")?;
let client = Client::builder()
.proxy(proxy)
.build()?;
let response = client.get("https://httpbin.org/ip").send()?;
println!("Response: {}", response.text()?);
Ok(())
}use reqwest::Client;
use tokio;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new();
// Make concurrent requests
let urls = vec![
"https://httpbin.org/get",
"https://httpbin.org/ip",
"https://httpbin.org/headers",
];
let handles: Vec<_> = urls.into_iter()
.map(|url| {
let client = client.clone();
tokio::spawn(async move {
client.get(url).send().await?.text().await
})
})
.collect();
for handle in handles {
let result = handle.await??;
println!("Response: {} bytes", result.len());
}
Ok(())
}use reqwest::blocking::Client;
use std::io::Read;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new();
let mut response = client.get("https://httpbin.org/stream/5").send()?;
let mut buffer = [0u8; 1024];
loop {
let bytes_read = response.read(&mut buffer)?;
if bytes_read == 0 {
break;
}
println!("Read {} bytes", bytes_read);
}
Ok(())
}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()?;
// Check status
println!("Status: {}", response.status());
println!("Is success: {}", response.status().is_success());
println!("Is client error: {}", response.status().is_client_error());
// Check headers
let content_type = response.headers().get("content-type");
println!("Content-Type: {:?}", content_type);
// Check URL (after redirects)
println!("Final URL: {}", response.url());
// Version
println!("HTTP version: {:?}", response.version());
Ok(())
}use reqwest::blocking::Client;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new();
let response = client
.get("https://httpbin.org/put")
.header("X-Custom", "value")
.header("Accept", "application/json")
.query(&["key", "value"])
.body("request body")
.send()?;
println!("Status: {}", response.status());
Ok(())
}use reqwest::blocking::Client;
use serde_json::json;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new();
// PUT request
let put_response = client
.put("https://httpbin.org/put")
.json(&json!({"updated": true}))
.send()?;
println!("PUT: {}", put_response.status());
// DELETE request
let delete_response = client
.delete("https://httpbin.org/delete")
.send()?;
println!("DELETE: {}", delete_response.status());
Ok(())
}use reqwest::blocking::Client;
use std::time::Duration;
use std::thread;
fn fetch_with_retry(url: &str, max_retries: u32) -> Result<String, Box<dyn std::error::Error>> {
let client = Client::builder()
.timeout(Duration::from_secs(5))
.build()?;
for attempt in 0..max_retries {
match client.get(url).send() {
Ok(response) if response.status().is_success() => {
return Ok(response.text()?);
}
Ok(response) => {
eprintln!("Attempt {}: HTTP {}", attempt + 1, response.status());
}
Err(e) => {
eprintln!("Attempt {}: Error {}", attempt + 1, e);
}
}
if attempt < max_retries - 1 {
thread::sleep(Duration::from_millis(100 * (attempt + 1)));
}
}
Err("Max retries exceeded".into())
}
fn main() {
match fetch_with_retry("https://httpbin.org/get", 3) {
Ok(body) => println!("Success: {} bytes", body.len()),
Err(e) => eprintln!("Failed: {}", e),
}
}use reqwest::blocking::Client;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::builder()
.user_agent("MyApp/1.0 (contact@example.com)")
.build()?;
let response = client.get("https://httpbin.org/user-agent").send()?;
println!("Response: {}", response.text()?);
Ok(())
}Reqwest Key Imports:
// Blocking API
use reqwest::blocking::{Client, get};
// Async API
use reqwest::Client;
// Common
use reqwest::{Method, StatusCode, header};HTTP Methods:
| Method | Client Method |
|--------|---------------|
| GET | client.get(url) |
| POST | client.post(url) |
| PUT | client.put(url) |
| DELETE | client.delete(url) |
| PATCH | client.patch(url) |
| HEAD | client.head(url) |
Response Body Methods:
| Method | Returns |
|--------|---------|
| .text() | String |
| .json() | Deserialized type |
| .bytes() | Vec<u8> |
| .copy_to(writer) | Writes to impl Write |
Common Headers:
use reqwest::header::*;
USER_AGENT, CONTENT_TYPE, AUTHORIZATION, ACCEPT,
CACHE_CONTROL, COOKIE, SET_COOKIEClient Configuration:
let client = Client::builder()
.timeout(Duration::from_secs(10))
.connect_timeout(Duration::from_secs(5))
.user_agent("MyApp/1.0")
.default_headers(headers)
.redirect(redirect::Policy::limited(10))
.build()?;Key Points:
Client for multiple requestsreqwest::get() is convenient for one-off requests.json() requires serde featurecookies feature? operator.status().is_success() before processing