Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Lesson 8 — Networking with Reqwest and Hyper


🎯 Learning Objectives

  • Hiểu sự khác biệt giữa reqwest (high-level HTTP client) và hyper (low-level HTTP library).
  • Biết cách gửi HTTP request cơ bản với reqwest.
  • Biết cách xây dựng HTTP server đơn giản với hyper.
  • Thực hành viết ứng dụng nhỏ kết hợp client + server.

✅ Explanation & Key Concepts

Reqwest

  • Dựa trên hyper nhưng cung cấp API thân thiện.
  • Hỗ trợ async/await, JSON, cookie, TLS.

Hyper

  • Thư viện HTTP low-level, rất nhanh và linh hoạt.
  • Thường dùng để viết custom server hoặc proxy.

Khi nào dùng

  • Client nhanh: dùng reqwest.
  • Server tùy biến cao: dùng hyper.
  • Có thể kết hợp (reqwest cho client, hyper cho server).

💻 Example Implementation

Cargo.toml


[package]
name = "lesson08_networking"
version = "0.1.0"
edition = "2024"

[dependencies]
reqwest = { version = "0.11"}
hyper = { version = "1", features = ["full"] }
hyper-util={ version="0.1", features=["full"] }
http-body-util="0.1"
tokio = { version = "1", features = ["full"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"

src/main.rs


// cargo-deps: reqwest="0.11", hyper={ version="1", features=["full"] }, hyper-util={ version="0.1", features=["full"] }, http-body-util="0.1", tokio={ version="1", features=["full"] }, serde={ version="1", features=["derive"] }, serde_json="1"

use std::time::Duration;
use bytes::Bytes;
use http_body_util::Full;
use hyper::{Request, Response};
use hyper::server::conn::http1;
use hyper::service::service_fn;
use hyper_util::rt::TokioIo;
use tokio::net::TcpListener;

use reqwest::Client;
use serde::Deserialize;

#[derive(Deserialize, Debug)]
struct Todo {
    user_id: u32,
    id: u32,
    title: String,
    completed: bool,
}

async fn handle(_req: Request<hyper::body::Incoming>) -> Result<Response<Full<Bytes>>, hyper::Error> {
    Ok(Response::new(Full::new(Bytes::from_static(
        b"Hello from Hyper 1.x server!",
    ))))
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    tokio::spawn(async move {
        let addr = "127.0.0.1:3000";
        let listener = TcpListener::bind(addr).await.expect("bind");
        println!("Server running on http://{addr}");

        loop {
            let (stream, _) = listener.accept().await.expect("accept");
            let io = TokioIo::new(stream);
            tokio::spawn(async move {
                let svc = service_fn(handle);
                if let Err(err) = http1::Builder::new().serve_connection(io, svc).await {
                    eprintln!("server error: {err}");
                }
            });
        }
    });

    // ---- Reqwest client fetch JSON ----
    let client = Client::builder()
        .connect_timeout(Duration::from_secs(5))
        .timeout(Duration::from_secs(15))
        .build()?;

    let todo: Todo = client
        .get("https://jsonplaceholder.typicode.com/todos/1")
        .send()
        .await?
        .error_for_status()?  // treat 4xx/5xx as errors
        .json()
        .await?;

    println!(
        "Fetched TODO #{} (user {}): '{}' — completed? {}",
        todo.id, todo.user_id, todo.title, todo.completed
    );

    Ok(())
}

🛠️ Hands-on Exercises

  1. Basic: Dùng reqwest để fetch JSON từ API công khai và in ra trường title.
  2. Intermediate: Dùng hyper viết server trả JSON thay vì plain text.
  3. Challenge: Viết proxy mini: client gửi request tới server hyper, server gọi reqwest fetch API khác và trả kết quả.

🐞 Common Pitfalls & Debugging Tips

Common Pitfalls

  • Quên bật feature json cho reqwest → không dùng được .json().
  • Không spawn tokio runtime (#[tokio::main]).
  • Hyper yêu cầu return Result<Response<Body>, Error>; dễ sai lifetime.

🔄 Migration Notes (Rust 2024+)

Migration Guidance

  • Reqwest/Hypers tương thích Rust 2024.
  • Hyper v1 đang phát triển, APIs có thể thay đổi.
  • Nên tách client/server code thành module riêng cho maintain dễ.

📚 References


❓ Q & A — Câu hỏi thường gặp

Q1. Khi nào nên dùng Reqwest thay vì Hyper?

  • Khi bạn cần HTTP client nhanh, dễ dùng, có sẵn JSON, cookie, và async/await — dùng Reqwest. Còn Hyper phù hợp khi bạn cần tùy biến thấp tầng hoặc viết HTTP server/proxy.

Q2. Ưu và nhược điểm của high-level vs low-level API là gì?

  • High-level (Reqwest) dễ dùng, tiết kiệm thời gian nhưng khó kiểm soát chi tiết; low-level (Hyper) linh hoạt và hiệu năng cao nhưng cần nhiều boilerplate và hiểu sâu về HTTP.

Q3. Làm sao để kết hợp Reqwest và Hyper trong cùng project?

  • Dùng Hyper cho server-side và Reqwest cho client-side. Hai thư viện này tương thích hoàn toàn vì Reqwest được xây dựng dựa trên Hyper.

📖 Glossary of Terms

Key Terms

  • Reqwest: HTTP client high-level dựa trên Hyper.
  • Hyper: HTTP library low-level, linh hoạt, nhanh.
  • ServiceFn: adapter để viết service trong Hyper.
  • Body: kiểu dữ liệu đại diện cho HTTP body.

🌿 Wisdom Note

Đạo Đức Kinh — Chương 32

Đạo thường vô danh.

The Tao is forever nameless.

Networking abstractions cũng vậy: bề ngoài nhiều thư viện, nhưng bản chất là truyền dữ liệu qua TCP/HTTP.