How to use hyper crate in Rust HTTP

Use `hyper` by selecting either the `client` or `server` feature, then instantiate the corresponding struct and run it within an async runtime like `tokio`.

Use hyper by selecting either the client or server feature, then instantiate the corresponding struct and run it within an async runtime like tokio. For clients, you create a Client to send requests; for servers, you create a Server with a service that handles incoming connections.

Here is a minimal example of a client fetching data and a server echoing requests:

// Cargo.toml dependencies:
// [dependencies]
// hyper = { version = "1.0", features = ["full"] }
// tokio = { version = "1", features = ["full"] }
// http-body-util = "0.1"

use hyper::{Body, Client, Request, Response, Server, service::service_fn};
use http_body_util::BodyExt;
use std::convert::Infallible;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // --- Client Example ---
    let client = Client::builder(hyper::rt::TokioExecutor::new()).build_http();
    let req = Request::builder()
        .uri("https://httpbin.org/get")
        .body(Body::empty())?;
    
    let res = client.request(req).await?;
    let body = res.into_body().collect().await?.to_bytes();
    println!("Client received: {}", String::from_utf8_lossy(&body));

    // --- Server Example ---
    let addr = ([127, 0, 0, 1], 3000).into();
    let make_svc = || {
        let service = service_fn(|_req| async {
            Ok::<_, Infallible>(Response::new(Body::from("Hello, Hyper!")))
        });
        Ok::<_, Infallible>(service)
    };

    let server = Server::bind(&addr).serve(make_svc);
    println!("Server listening on http://{}", addr);
    server.await?;

    Ok(())
}

Key implementation details to remember:

  1. Async Runtime: hyper 1.0 requires an async executor. tokio is the standard choice; ensure you enable the full feature or explicitly select client/server and http1/http2 in your Cargo.toml.
  2. Body Handling: In hyper 1.0, request and response bodies are streams. You must use http-body-util (or similar) to collect the body into bytes or strings, as shown with .collect().await.
  3. Service Trait: The server accepts a MakeService factory. The simplest approach is service_fn, which wraps an async closure that returns a Response.
  4. Error Handling: The Infallible type is used for the service error when your handler cannot fail, simplifying the signature.

For production, you will likely need to add middleware (like logging or compression) using tower or hyper-util, and handle TLS via rustls or native-tls features.