Try it yourself with our free Curl Converter tool — runs entirely in your browser, no signup needed.

How to Make HTTP requests in Rust

How to make HTTP requests in Rust

Making HTTP requests is a fundamental task in many web development projects, and Rust is no exception. In this guide, we will explore how to make HTTP requests in Rust, covering the basics, common edge cases, and performance tips.

Quick Example

Here is a minimal example that makes a GET request to a URL:

use reqwest;

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let res = reqwest::get("https://httpbin.org/ip").await?;
    println!("Status: {}", res.status());
    println!("Body: {}", res.text().await?);
    Ok(())
}

Add the following dependency to your Cargo.toml file:

[dependencies]
reqwest = "0.11"
tokio = { version = "1", features = ["full"] }

Run cargo run to execute the example.

Step-by-Step Breakdown

Let's walk through the code:

  • use reqwest;: We import the reqwest crate, which provides a simple and convenient API for making HTTP requests.
  • #[tokio::main]: This attribute tells Tokio to run the main function as an asynchronous task.
  • async fn main() -> Result<(), reqwest::Error> { ... }: We define an asynchronous main function that returns a Result type, which allows us to handle errors in a concise way.
  • let res = reqwest::get("https://httpbin.org/ip").await?;: We use the reqwest::get function to make a GET request to the specified URL. The await? syntax allows us to wait for the response and propagate any errors that may occur.
  • println!("Status: {}", res.status());: We print the HTTP status code of the response.
  • println!("Body: {}", res.text().await?);: We print the response body as text, waiting for the response to complete if necessary.

Handling Edge Cases

Empty/null input

If the input URL is empty or null, we should handle the error accordingly:

let url = "";
match reqwest::get(url) {
    Err(e) => println!("Error: {}", e),
    Ok(res) => println!("Status: {}", res.status()),
}

Invalid input

If the input URL is invalid, we should handle the error accordingly:

let url = " invalid url ";
match reqwest::get(url) {
    Err(e) => println!("Error: {}", e),
    Ok(res) => println!("Status: {}", res.status()),
}

Large input

If the input URL is very large, we may need to increase the request timeout:

let url = "https://httpbin.org/stream/1000000";
let client = reqwest::Client::builder()
    .timeout(std::time::Duration::from_secs(30))
    .build()?;
let res = client.get(url).await?;

Unicode/special characters

If the input URL contains Unicode or special characters, we should ensure that the URL is properly encoded:

let url = "https://httpbin.org/ip?param=é";
let encoded_url = url.replace(" ", "%20");
let res = reqwest::get(encoded_url).await?;

Common Mistakes

Mistake 1: Not handling errors

// WRONG
let res = reqwest::get("https://httpbin.org/ip").await;
println!("Status: {}", res.status());

// CORRECT
let res = reqwest::get("https://httpbin.org/ip").await?;
println!("Status: {}", res.status());

Mistake 2: Not waiting for the response

// WRONG
let res = reqwest::get("https://httpbin.org/ip");
println!("Status: {}", res.status());

// CORRECT
let res = reqwest::get("https://httpbin.org/ip").await?;
println!("Status: {}", res.status());

Mistake 3: Not using the Client builder

// WRONG
let res = reqwest::get("https://httpbin.org/ip");

// CORRECT
let client = reqwest::Client::builder().build()?;
let res = client.get("https://httpbin.org/ip").await?;

Performance Tips

Tip 1: Use the Client builder

Using the Client builder allows you to configure the client instance and improve performance.

let client = reqwest::Client::builder()
    .timeout(std::time::Duration::from_secs(30))
    .build()?;

Tip 2: Use the async API

Using the async API allows you to write non-blocking code and improve performance.

let res = reqwest::get("https://httpbin.org/ip").await?;

Tip 3: Use the Tokio runtime

Using the Tokio runtime allows you to write concurrent code and improve performance.

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    // ...
}

FAQ

Q: What is the difference between reqwest and hyper?

A: reqwest is a high-level HTTP client library built on top of hyper, which is a low-level HTTP library.

Q: How do I handle errors in reqwest?

A: You can use the ? operator to propagate errors, or use a match statement to handle errors explicitly.

Q: Can I use reqwest with async/await?

A: Yes, reqwest supports async/await out of the box.

Q: How do I configure the reqwest client?

A: You can use the Client builder to configure the client instance.

Q: Is reqwest compatible with Tokio?

A: Yes, reqwest is compatible with Tokio and can be used with the Tokio runtime.

AI agent tools available. The CodeTidy MCP Server gives Claude, Cursor, and other AI agents access to 60+ developer tools. One command: npx @codetidy/mcp