Rust and reqwest

I’ve covered a few topics around Rust lately on this blog. Hopefully around technologies that are most likely to be used in many real world applications. This post is about one of the missing pieces – how do we call our web API’s/services etc.

In C# we have the HttpClient which is the usual type for such use cases. With Rust there are various options, but as the title suggests, we’re going to concentrate on reqwest.

All we really need to do is supply a couple of crates to Cargo.toml, as you’ll have guessed, one is reqwest. The other is tokio because I’m waiting to use async/await. So create yourself a project then update Cargo.toml to add these dependencies

reqwest = "0.12.23"
tokio = { version = "1.47.1", features = ["rt", "rt-multi-thread", "macros"] }

Next up, open src/main.rs (or create one) and let’s add a simply GET call

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
let result = reqwest::get("https://httpbin.org/get")
  .await?
  .text()
  .await?;

  println!("{}", result);
  Ok(())
}

This is a “shortcut” to use a get method.

The following is a longer form and is what we’d use for other HTTP methods, but I’m showing how we can generate a RequestBuilder (the type returned from client.get) and then send this and retrieve the response

let client = reqwest::Client::new();
let result = client.get("https://httpbin.org/get");
let result = result.send().await?.text().await?;

Other HTTP methods, such as POST, DELETE etc. can be created from the RequestBuilder, for example

let post = client.post("https://httpbin.org/post")
  .body("hello world")
  .header("Content-Type", "text/plain");

let result = post.send().await?.text().await?;

JSON instead of plan text

Often we’ll want to deserialize to types, i.e. via JSON, so update Cargo.toml to lok like this

[dependencies]
reqwest = { version = "0.12.23", features = ["json"] }
tokio = { version = "1.47.1", features = ["rt", "rt-multi-thread", "macros"] }
serde = { version = "1.0.219", features = ["derive"] }

Now change main.rs to add this code to the start of the file

use serde::Deserialize;

#[derive(Deserialize)]
struct ApiResponse {
    message: String,
}

ApiResponse will represent our object and we use the following

let client = reqwest::Client::new();
let result = client.get("https://your_api");
let result = result
        .send()
        .await?
        .json::<ApiResponse>()
        .await?;

println!("{}", result.message);