HTTP Client in Rust: Making Requests the Right Way

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

HTTP client in Rust: making requests correctly



Rust is a modern systems programming language that combines the performance of C++ with memory safety. When developing web applications, microservices, or command-line tools, there is often a need to interact with external APIs. In this article, we will look at how to create an HTTP client in Rust using the popular crates reqwest and ureq. You will learn how to send GET and POST requests, handle errors, and work with JSON.



Why Rust for HTTP requests?



Rust offers unique advantages for working with the network:



  • Memory safety — the compiler guarantees the absence of leaks and data races.
  • High performance — speed comparable to C/C++.
  • Asynchrony — built-in support for async/await for efficient I/O operations.
  • Crate ecosystem — thousands of ready-made libraries, including HTTP clients.


There are two main approaches to working with HTTP in Rust: synchronous (blocking) and asynchronous (non-blocking). We will look at both.



Project setup and crate selection



Let's create a new Rust project:



cargo new rust-http-clientcd rust-http-client


Open Cargo.toml and add dependencies:



[dependencies]# For asynchronous requestsreqwest = { version = "0.12", features = ["json"] }tokio = { version = "1", features = ["full"] }

# For synchronous requests (alternative)ureq = "2.9"


Crate comparison:



  • reqwest — the most popular HTTP client. Supports asynchrony, JSON, cookies, proxies.
  • ureq — a lightweight synchronous client. Ideal for simple scripts and CLI tools.


1. GET request with reqwest (asynchronous)



Let's start with an asynchronous GET request. Create the file src/main.rs:



use reqwest;use std::error::Error;

#[tokio::main]async fn main() -> Result<(), Box<dyn Error>> { // Send GET request let response = reqwest::get("https://api.github.com/repos/rust-lang/rust") .await? .text() .await?;

println!("Response from GitHub API:"); println!("{}", &response[..500]); // Print first 500 characters

Ok(())}


Explanation:



  • #[tokio::main] — macro for launching the Tokio async runtime.
  • reqwest::get() — sends a GET request and returns a Response.
  • .await? — awaits the completion of the operation and handles errors.
  • .text() — extracts the response body as a string.


Run the project:



cargo run


You will see a JSON response from the GitHub API.



2. POST request with JSON (reqwest)



Now let's send a POST request with a JSON body:



use reqwest;use serde::{Deserialize, Serialize};use std::error::Error;

#[derive(Serialize, Deserialize, Debug)]struct Post { title: String, body: String, user_id: u32,}

#[derive(Deserialize, Debug)]struct CreatedPost { id: u32, title: String,}

#[tokio::main]async fn main() -> Result<(), Box<dyn Error>> { // Create a client with settings let client = reqwest::Client::new();

// Data to send let new_post = Post { title: "HTTP client in Rust".to_string(), body: "Complete guide to working with HTTP in Rust".to_string(), user_id: 1, };

// Send POST request let response = client .post("https://jsonplaceholder.typicode.com/posts") .json(&new_post) .send() .await?;

//

Blogs

Book Recommendations