ugi 0.2.1

Runtime-agnostic Rust request client with HTTP/1.1, HTTP/2, HTTP/3, H2C, WebSocket, SSE, and gRPC support
Documentation
use std::net::SocketAddr;
use std::time::Duration;

use futures_lite::future::block_on;
use serde::Deserialize;

#[derive(Debug, Deserialize)]
struct User {
    id: u64,
    name: String,
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    block_on(async move {
        let local_addr: SocketAddr = "0.0.0.0:0".parse()?;
        let client = ugi::Client::builder()
            .base_url("https://api.example.com")?
            .bearer_auth("token")?
            .cookie_store()
            .dns_prefetch(["api.example.com"])
            .connect_timeout(Duration::from_secs(3))
            .read_timeout(Duration::from_secs(10))
            .local_addr(local_addr)
            .build()?;

        let response = client
            .get("/users/1")
            .header("x-request-id", "demo-001")?
            .await?;
        let metrics = response.metrics().clone();
        let user: User = response.json().await?;

        println!("user#{} {}", user.id, user.name);
        println!(
            "protocol={:?} ttfb={:?}",
            metrics.protocol(),
            metrics.ttfb()
        );
        Ok(())
    })
}