In Rust, reqwest
provides several flexible ways to pass query parameters in GET requests. You can use the .query()
method with different data structures or manually construct URLs with query strings.
Method 1: Using HashMap
The most common approach uses a HashMap
to store key-value pairs:
use reqwest;
use std::collections::HashMap;
#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
let client = reqwest::Client::new();
// Create parameters using HashMap
let mut params = HashMap::new();
params.insert("q", "rust programming");
params.insert("limit", "10");
params.insert("offset", "0");
let response = client
.get("https://api.example.com/search")
.query(¶ms)
.send()
.await?;
println!("Status: {}", response.status());
println!("Response: {}", response.text().await?);
Ok(())
}
Method 2: Using Tuples and Slices
For simpler cases, you can use tuples or slices:
use reqwest;
#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
let client = reqwest::Client::new();
// Using array of tuples
let params = [
("q", "web scraping"),
("format", "json"),
("page", "1")
];
let response = client
.get("https://api.example.com/data")
.query(¶ms)
.send()
.await?;
println!("Response: {}", response.text().await?);
Ok(())
}
Method 3: Using Vectors of Tuples
When you need dynamic parameter construction:
use reqwest;
#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
let client = reqwest::Client::new();
// Build parameters dynamically
let mut params = Vec::new();
params.push(("api_key", "your_api_key"));
params.push(("format", "json"));
// Conditionally add parameters
if let Some(user_id) = get_user_id() {
params.push(("user_id", &user_id));
}
let response = client
.get("https://api.example.com/user")
.query(¶ms)
.send()
.await?;
println!("Response: {}", response.text().await?);
Ok(())
}
fn get_user_id() -> Option<String> {
Some("12345".to_string())
}
Method 4: Multiple Query Calls
You can chain multiple .query()
calls to build parameters incrementally:
use reqwest;
#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
let client = reqwest::Client::new();
let mut request = client.get("https://api.example.com/search");
// Add base parameters
request = request.query(&[("format", "json")]);
// Conditionally add more parameters
if true { // Some condition
request = request.query(&[("include_metadata", "true")]);
}
// Add final parameters
request = request.query(&[("limit", "50")]);
let response = request.send().await?;
println!("Response: {}", response.text().await?);
Ok(())
}
Method 5: Using Serializable Structs
For complex parameter structures, use serde
:
use reqwest;
use serde::Serialize;
#[derive(Serialize)]
struct SearchParams {
q: String,
limit: u32,
offset: u32,
#[serde(skip_serializing_if = "Option::is_none")]
category: Option<String>,
}
#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
let client = reqwest::Client::new();
let params = SearchParams {
q: "rust web scraping".to_string(),
limit: 25,
offset: 0,
category: Some("programming".to_string()),
};
let response = client
.get("https://api.example.com/search")
.query(¶ms)
.send()
.await?;
println!("Response: {}", response.text().await?);
Ok(())
}
Error Handling and Best Practices
Here's a more robust example with proper error handling:
use reqwest;
use std::collections::HashMap;
#[tokio::main]
async fn main() {
if let Err(e) = make_request().await {
eprintln!("Request failed: {}", e);
}
}
async fn make_request() -> Result<(), Box<dyn std::error::Error>> {
let client = reqwest::Client::new();
let mut params = HashMap::new();
params.insert("api_key", "your_api_key");
params.insert("query", "rust programming");
let response = client
.get("https://api.example.com/search")
.query(¶ms)
.timeout(std::time::Duration::from_secs(30))
.send()
.await?;
// Check if request was successful
if response.status().is_success() {
let text = response.text().await?;
println!("Success: {}", text);
} else {
println!("Request failed with status: {}", response.status());
}
Ok(())
}
Cargo.toml Dependencies
Add these dependencies to your Cargo.toml
:
[dependencies]
reqwest = { version = "0.11", features = ["json"] }
tokio = { version = "1", features = ["full"] }
serde = { version = "1.0", features = ["derive"] }
URL Encoding
reqwest
automatically URL-encodes query parameters, so you don't need to worry about special characters:
let params = [
("q", "hello world & special chars!"),
("filter", "category:rust OR category:web-scraping")
];
// Results in: ?q=hello%20world%20%26%20special%20chars%21&filter=category%3Arust%20OR%20category%3Aweb-scraping
Choose the method that best fits your use case: HashMap for dynamic parameters, tuples for simple static parameters, or structs for complex, typed parameter structures.