Reqwest is a popular Rust crate for making HTTP requests. It supports both synchronous and asynchronous operations. To make concurrent requests using Reqwest's async functionality, you can use Rust's async
and await
syntax along with the tokio
runtime, which is an asynchronous runtime for Rust.
Here's a step-by-step guide on how to make concurrent requests with Reqwest and Tokio:
- Add Dependencies: First, you need to include
reqwest
andtokio
in yourCargo.toml
.
[dependencies]
reqwest = { version = "0.11", features = ["json", "async-std-runtime"] }
tokio = { version = "1", features = ["full"] }
- Set Up Async Main Function: Use the
#[tokio::main]
attribute to define an asynchronous main function where your code will run.
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Your asynchronous code goes here
Ok(())
}
- Make Concurrent Requests: Create multiple async tasks for your requests and use
futures::future::join_all
to wait for all of them to complete.
Here's a complete example of making concurrent GET requests to multiple URLs:
use reqwest; // 0.11
use tokio; // 1.0
use futures::future::join_all;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// List of URLs to fetch.
let urls = vec![
"http://example.com",
"http://example.org",
"http://example.net",
];
// Create a Reqwest client. It's recommended to reuse a client instead of creating a new one for each request.
let client = reqwest::Client::new();
// Create a vector to hold our futures.
let mut futures = Vec::new();
// Iterate over the URLs and spawn a future for each one.
for url in urls {
// Clone the client to use it inside the async block.
let client = client.clone();
let future = async move {
let response = client.get(url).send().await?;
response.text().await
};
// Push the future onto our list of futures.
futures.push(future);
}
// Use `join_all` to wait for all the futures to complete.
let responses = join_all(futures).await;
// Iterate through the results.
for response in responses {
match response {
Ok(content) => println!("Fetched content: {}", content),
Err(e) => eprintln!("Error: {}", e),
}
}
Ok(())
}
In this example, we're creating an async task for each URL, which sends an HTTP GET request and then awaits its response. The join_all
function is used to wait for all the futures (requests) to complete. The results are then printed to the console.
Note that join_all
returns a Vec
of Result
s, one for each future, so we can handle potential errors for each request individually.
Remember to always handle errors properly in a real-world application and respect the terms of service or robots.txt of the websites you are scraping.
Finally, make sure you're using a recent version of tokio
and reqwest
to ensure compatibility with the provided code. You can check the latest versions available on crates.io.