### HTTP Upgrades Example (WebSockets) Source: https://github.com/hyperium/hyper/blob/master/examples/README.md Demonstrates how to perform HTTP upgrades, such as establishing WebSocket connections. Includes both server and client code for the upgrade process. ```rust use futures_util::{SinkExt, StreamExt}; use hyper::server::conn::AddrStream; use hyper::service::{make_service_fn, service_fn}; use hyper::{Body, Request, Response, Server, StatusCode}; use hyper_util::rt::TokioIo; use std::convert::Infallible; use std::net::SocketAddr; use tokio_tungstenite::tungstenite::Message; use tokio_tungstenite::WebSocketStream; async fn handle_request(req: Request, src: SocketAddr) -> Result, Box> { if req.method() == hyper::Method::GET && req.uri().path() == "/websocket" { let (ws, _) = hyper_upgrade::upgrade(req)?; tokio::spawn(async move { let websocket = WebSocketStream::from_tokio(TokioIo::new(ws)); handle_websocket(websocket, src).await; }); Ok(Response::new(Body::empty())) } else { let mut resp = Response::new(Body::from("Hello World!")); *resp.status_mut() = StatusCode::OK; Ok(resp) } } async fn handle_websocket(mut websocket: WebSocketStream>, src: SocketAddr) { while let Some(msg) = websocket.next().await { match msg { Ok(Message::Text(text)) => { println!("Received message from {{}}: {{}}", src, text); let response = format!("Echo: {}", text); if websocket.send(Message::Text(response)).await.is_err() { eprintln!("Failed to send message to {}", src); break; } } Ok(Message::Binary(bin)) => { println!("Received binary from {{}}: {{:?}}", src, bin); if websocket.send(Message::Binary(bin)).await.is_err() { eprintln!("Failed to send binary message to {}", src); break; } } Ok(Message::Close(_)) => { println!("Connection closed by {}", src); break; } Err(e) => { eprintln!("WebSocket error from {{}}: {}", src, e); break; } _ => {}, } } } #[tokio::main] async fn main() -> Result<(), Box> { let addr = ([127, 0, 0, 1], 3000).into(); let make_svc = make_service_fn(|conn: AddrStream| { let src = conn.remote_addr(); async move { Ok::<_, Infallible>(service_fn(move |req| handle_request(req, src))) } }); let server = Server::bind(&addr).serve(make_svc); println!("Listening on http://{{}}", addr); server.await?; Ok(()) } ``` -------------------------------- ### Simple HTTP Client Example Source: https://github.com/hyperium/hyper/blob/master/examples/README.md A basic CLI client that fetches content from a given URL and prints it chunk by chunk. Requires the URL as a command-line parameter. ```rust use hyper::client::HttpConnector; use hyper::Body; use hyper::Client; use hyper_util::rt::TokioIo; use std::error::Error; #[tokio::main] async fn main() -> Result<(), Box> { let url = std::env::args().nth(1).ok_or("Please provide a URL")?; let url = url.parse::()?; let client = Client::builder().build::<_, Body>(HttpConnector::new()); let resp = client.get(url).await?; let mut stream = ""; let mut body_bytes = Vec::new(); let mut stream = hyper::body::BodyStream::new(resp.into_body()); while let Some(chunk) = stream.next().await { let chunk = chunk?; body_bytes.extend_from_slice(&chunk); } let body_str = String::from_utf8(body_bytes)?; println!("{}", body_str); Ok(()) } ``` -------------------------------- ### Simple "Hello World" Server Source: https://github.com/hyperium/hyper/blob/master/examples/README.md A minimal HTTP server that responds with "Hello World!". Demonstrates basic server setup. ```rust use hyper::service::{make_service_fn, service_fn}; use hyper::{Body, Request, Response, Server, StatusCode}; use std::convert::Infallible; async fn hello(_req: Request) -> Result, Infallible> { Ok(Response::new(Body::from("Hello World!"))) } #[tokio::main] async fn main() -> Result<(), Box> { let addr = ([127, 0, 0, 1], 3000).into(); let make_svc = make_service_fn(|_| async { Ok::<_, Infallible>(service_fn(hello)) }); let server = Server::bind(&addr).serve(make_svc); println!("Listening on http://{{}}", addr); server.await?; Ok(()) } ``` -------------------------------- ### TOML Dependencies for Hyper Examples Source: https://github.com/hyperium/hyper/blob/master/examples/README.md This TOML block lists the dependencies required to run the hyper examples. Ensure these are included in your Cargo.toml file. ```toml [dependencies] hyper = { version = "1", features = ["full"] } tokio = { version = "1", features = ["full"] } pretty_env_logger = "0.5" http-body-util = "0.1" bytes = "1" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" form_urlencoded = "1" http = "1" utures-util = { version = "0.3", default-features = false } ``` -------------------------------- ### Build and install shared library with cargo-c Source: https://github.com/hyperium/hyper/blob/master/capi/README.md If you are using `cargo-c`, this command builds and installs a shared library with the unstable C API. It also enables client, HTTP/1, HTTP/2, and FFI features. ```bash RUSTFLAGS="--cfg hyper_unstable_ffi" cargo cbuild --features client,http1,http2,ffi --release ``` -------------------------------- ### JSON Client Example Source: https://github.com/hyperium/hyper/blob/master/examples/README.md Fetches JSON data from a URL, reads the body asynchronously, and parses it using serde. Useful for interacting with JSON APIs. ```rust use hyper::client::HttpConnector; use hyper::Body; use hyper::Client; use hyper_util::rt::TokioIo; use serde::Deserialize; use std::error::Error; #[derive(Deserialize, Debug)] struct User { name: String, } #[tokio::main] async fn main() -> Result<(), Box> { let url = std::env::args().nth(1).ok_or("Please provide a URL")?; let url = url.parse::()?; let client = Client::builder().build::<_, Body>(HttpConnector::new()); let resp = client.get(url).await?; let body_bytes = hyper::body::to_bytes(resp.into_body()).await?; let user: User = serde_json::from_slice(&body_bytes)?; println!("{:?}", user); Ok(()) } ``` -------------------------------- ### Send File Server Example Source: https://github.com/hyperium/hyper/blob/master/examples/README.md A server that asynchronously reads files using tokio-util and sends their content back to the client. Demonstrates efficient file serving. ```rust use hyper::service::{make_service_fn, service_fn}; use hyper::{Body, Request, Response, Server, StatusCode}; use tokio::fs::File; use tokio_util::codec::{BytesCodec, FramedRead}; use std::convert::Infallible; use std::path::PathBuf; async fn send_file(req: Request) -> Result, Box> { let mut path = PathBuf::from("./files"); path.push(req.uri().path().trim_start_matches('/')); match File::open(&path).await { Ok(file) => { let stream = FramedRead::new(file, BytesCodec); let body = Body::wrap_stream(stream); Ok(Response::new(body)) } Err(_) => { let mut resp = Response::new(Body::from("File not found")); *resp.status_mut() = StatusCode::NOT_FOUND; Ok(resp) } } } #[tokio::main] async fn main() -> Result<(), Box> { let addr = ([127, 0, 0, 1], 3000).into(); let make_svc = make_service_fn(|_| async { Ok::<_, Infallible>(service_fn(send_file)) }); let server = Server::bind(&addr).serve(make_svc); println!("Listening on http://{{}}", addr); server.await?; Ok(()) } ``` -------------------------------- ### Echo Server Example Source: https://github.com/hyperium/hyper/blob/master/examples/README.md An echo server that reflects the POST request's body back in the response. Useful for testing request body handling. ```rust use hyper::service::{make_service_fn, service_fn}; use hyper::{Body, Request, Response, Server, StatusCode}; use hyper_util::rt::TokioIo; use std::convert::Infallible; async fn echo(req: Request) -> Result, Infallible> { let whole_body = hyper::body::to_bytes(req.into_body()).await?; Ok(Response::new(Body::from(whole_body))) } #[tokio::main] async fn main() -> Result<(), Box> { let addr = ([127, 0, 0, 1], 3000).into(); let make_svc = make_service_fn(|_| async { Ok::<_, Infallible>(service_fn(echo)) }); let server = Server::bind(&addr).serve(make_svc); println!("Listening on http://{{}}", addr); server.await?; Ok(()) } ``` -------------------------------- ### Graceful Shutdown Server Example Source: https://github.com/hyperium/hyper/blob/master/examples/README.md A server configured with a connection timeout and graceful shutdown capabilities. Ensures active connections are completed before the server stops. ```rust use hyper::service::{make_service_fn, service_fn}; use hyper::{Body, Request, Response, Server, StatusCode}; use std::convert::Infallible; use std::time::Duration; async fn hello(_req: Request) -> Result, Infallible> { tokio::time::sleep(Duration::from_secs(5)).await; Ok(Response::new(Body::from("Hello World!"))) } #[tokio::main] async fn main() -> Result<(), Box> { let addr = ([127, 0, 0, 1], 3000).into(); let make_svc = make_service_fn(|_| async { Ok::<_, Infallible>(service_fn(hello)) }); let server = Server::builder(tokio::net::TcpListener::bind(addr)) .tcp_nodelay(true) .serve(make_svc); let server = server.with_graceful_shutdown(async { tokio::signal::ctrl_c().await.unwrap(); }); println!("Listening on http://{{}}", addr); server.await?; Ok(()) } ``` -------------------------------- ### Web API Server Example Source: https://github.com/hyperium/hyper/blob/master/examples/README.md A server composed of two services: one that uppercases POST request content, and another that calls the first service and includes its response in its own. Demonstrates service composition. ```rust use hyper::service::{make_service_fn, service_fn}; use hyper::{Body, Request, Response, Server, StatusCode}; use std::convert::Infallible; async fn uppercase_service(req: Request) -> Result, Infallible> { let whole_body = hyper::body::to_bytes(req.into_body()).await?; let uppercased = String::from_utf8(whole_body.to_vec()).unwrap().to_uppercase(); Ok(Response::new(Body::from(uppercased))) } async fn composed_service(req: Request) -> Result, Infallible> { let resp1 = uppercase_service(req).await?; let body1_bytes = hyper::body::to_bytes(resp1.into_body()).await?; let body1_str = String::from_utf8(body1_bytes.to_vec()).unwrap(); Ok(Response::new(Body::from(format!("Service 1 response: {}", body1_str)))) } #[tokio::main] async fn main() -> Result<(), Box> { let addr = ([127, 0, 0, 1], 3000).into(); let make_svc = make_service_fn(|_| async { Ok::<_, Infallible>(service_fn(composed_service)) }); let server = Server::bind(&addr).serve(make_svc); println!("Listening on http://{{}}", addr); server.await?; Ok(()) } ``` -------------------------------- ### Reverse Proxy Gateway Example Source: https://github.com/hyperium/hyper/blob/master/examples/README.md A server acting as a gateway (reverse proxy) that forwards requests to another service, like the 'hello' service. Demonstrates request forwarding. ```rust use hyper::client::HttpConnector; use hyper::service::{make_service_fn, service_fn}; use hyper::{Body, Request, Response, Server, Uri}; use hyper_util::client::http1; use hyper_util::rt::TokioIo; use std::convert::Infallible; async fn handle_request(mut req: Request) -> Result, Box> { let uri = req.uri().clone(); let host = uri.host().ok_or("Invalid URI")?.to_string(); let port = uri.port_u16().unwrap_or(80); let path = uri.path(); let new_uri = format!("http://{}:{}{}", host, port, path); *req.uri_mut() = new_uri.parse::()?; let client = Client::new(); let resp = client.request(req).await?; Ok(resp) } #[tokio::main] async fn main() -> Result<(), Box> { let addr = ([127, 0, 0, 1], 3000).into(); let make_svc = make_service_fn(|_| async { Ok::<_, Infallible>(service_fn(handle_request)) }); let server = Server::bind(&addr).serve(make_svc); println!("Listening on http://{{}}", addr); server.await?; Ok(()) } ``` -------------------------------- ### Multi-Port Server Example Source: https://github.com/hyperium/hyper/blob/master/examples/README.md A server that listens on two different network ports, each with its own distinct service handler. Useful for routing different types of requests to different logic. ```rust use hyper::service::{make_service_fn, service_fn}; use hyper::{Body, Request, Response, Server, StatusCode}; use std::convert::Infallible; async fn handle_port1(_req: Request) -> Result, Infallible> { Ok(Response::new(Body::from("Hello from Port 1!"))) } async fn handle_port2(_req: Request) -> Result, Infallible> { Ok(Response::new(Body::from("Hello from Port 2!"))) } #[tokio::main] async fn main() -> Result<(), Box> { let addr1 = ([127, 0, 0, 1], 3000).into(); let addr2 = ([127, 0, 0, 1], 3001).into(); let make_svc1 = make_service_fn(|_| async { Ok::<_, Infallible>(service_fn(handle_port1)) }); let make_svc2 = make_service_fn(|_| async { Ok::<_, Infallible>(service_fn(handle_port2)) }); let server1 = Server::bind(&addr1).serve(make_svc1); let server2 = Server::bind(&addr2).serve(make_svc2); println!("Listening on http://{{}} and http://{{}}", addr1, addr2); tokio::join!(server1, server2); Ok(()) } ``` -------------------------------- ### Compile hyper with unstable C API Source: https://github.com/hyperium/hyper/blob/master/capi/README.md Use this command to compile the hyper library with the unstable C API enabled. Ensure you have Rust 1.64.0 or later. The `--features` flag includes necessary components for client functionality and HTTP versions. ```bash RUSTFLAGS="--cfg hyper_unstable_ffi" cargo rustc --features client,http1,http2,ffi --crate-type cdylib ``` -------------------------------- ### Check Rust Code Style (Mac/Linux) Source: https://github.com/hyperium/hyper/blob/master/docs/CODE_STYLE.md Use this command on Mac or Linux to check the formatting of all Rust files in the project using rustfmt. ```bash # Mac or Linux rustfmt --check --edition 2021 $(git ls-files '*.rs') ``` -------------------------------- ### Check Rust Code Style (Powershell) Source: https://github.com/hyperium/hyper/blob/master/docs/CODE_STYLE.md Use this Powershell command to check the formatting of all Rust files in the project using rustfmt. ```powershell # Powershell Get-ChildItem . -Filter "*.rs" -Recurse | foreach { rustfmt --check --edition 2021 $_.FullName } ``` -------------------------------- ### Configure Rust-Analyzer for Feature Checking Source: https://github.com/hyperium/hyper/blob/master/docs/CODE_STYLE.md Add these settings to your VS Code `settings.json` to ensure rust-analyzer considers all project features when checking code style. ```json { "rust-analyzer.cargo.features": ["full"], "rust-analyzer.check.features": ["full"] } ``` -------------------------------- ### Single-Threaded Server with !Send State Source: https://github.com/hyperium/hyper/blob/master/examples/README.md A server configured to run on a single thread, enabling the use of `!Send` application state like `Rc`. Useful when thread-safety is not required for state. ```rust use hyper::service::{make_service_fn, service_fn}; use hyper::{Body, Request, Response, Server, StatusCode}; use std::cell::RefCell; use std::convert::Infallible; use std::rc::Rc; struct AppState { counter: RefCell, } struct App { state: Rc, } impl Service> for App { type Response = Response; type Error = Infallible; type Future = futures_util::future::Ready>; fn call(&self, _req: Request) -> Self::Future { let mut counter = self.state.counter.borrow_mut(); *counter += 1; let response = Response::new(Body::from(format!("Request count: {}", *counter))); futures_util::future::ready(Ok(response)) } } #[tokio::main] async fn main() -> Result<(), Box> { let state = Rc::new(AppState { counter: RefCell::new(0), }); let make_svc = make_service_fn(move |_| { let state = Rc::clone(&state); async move { Ok::<_, Infallible>(App { state }) } }); let addr = ([127, 0 0 1], 3000).into(); let server = Server::bind(&addr).serve(make_svc); println!("Listening on http://{{}}", addr); server.await?; Ok(()) } ``` -------------------------------- ### Form Parameter Validation Server Source: https://github.com/hyperium/hyper/blob/master/examples/README.md A web server that accepts form data, specifically 'name' and 'number' parameters. It validates their presence and data types. Useful for handling user input. ```rust use bytes::Bytes; use futures_util::StreamExt; use http::StatusCode; use hyper::service::{make_service_fn, service_fn}; use hyper::{Body, Request, Response, Server}; use std::collections::HashMap; use std::convert::Infallible; async fn handle_request(req: Request) -> Result, Infallible> { let mut response = Response::new(Body::empty()); if req.method() == hyper::Method::POST { let mut body = BytesMut::new(); let mut stream = req.into_body(); while let Some(chunk) = stream.next().await { body.extend_from_slice(&chunk?); } let body_str = String::from_utf8(body.to_vec()).unwrap(); let params = form_urlencoded::parse(&body_str) .into_owned() .collect::>(); let name = params.get("name"); let number = params.get("number"); match (name, number) { (Some(n), Some(num_str)) => { if let Ok(num) = num_str.parse::() { *response.status_mut() = StatusCode::OK; *response.body_mut() = Body::from(format!("Hello, {{}}! Your number is {{}}.", n, num)); } else { *response.status_mut() = StatusCode::BAD_REQUEST; *response.body_mut() = Body::from("Invalid number format."); } } _ => { *response.status_mut() = StatusCode::BAD_REQUEST; *response.body_mut() = Body::from("Missing name or number parameter."); } } } else { *response.status_mut() = StatusCode::METHOD_NOT_ALLOWED; } Ok(response) } #[tokio::main] async fn main() -> Result<(), Box> { let addr = ([127, 0, 0, 1], 3000).into(); let make_svc = make_service_fn(|_| async { Ok::<_, Infallible>(service_fn(handle_request)) }); let server = Server::bind(&addr).serve(make_svc); println!("Listening on http://{{}}", addr); server.await?; Ok(()) } ``` -------------------------------- ### HTTP/S Proxy with CONNECT Tunneling Source: https://github.com/hyperium/hyper/blob/master/examples/README.md A proxy server that handles HTTP and HTTPS traffic, including CONNECT requests for tunneling. It forwards data between clients and remote servers. ```rust use hyper::client::HttpConnector; use hyper::server::conn::AddrStream; use hyper::service::{make_service_fn, service_fn}; use hyper::{Body, Request, Response, Server, StatusCode, Uri}; use hyper_util::client::http1; use hyper_util::rt::TokioIo; use std::convert::Infallible; use std::net::SocketAddr; async fn handle_request(req: Request, src: SocketAddr) -> Result, Box> { if req.method() == hyper::Method::CONNECT { let uri = req.uri().clone(); let host_port = uri.to_string(); tokio::spawn(async move { if let Err(e) = tunnel(host_port).await { eprintln!("Tunnel error: {}", e); } }); let mut resp = Response::new(Body::empty()); *resp.status_mut() = StatusCode::OK; return Ok(resp); } let url = req.uri().to_string(); let client = Client::new(); let resp = client.request(req).await?; Ok(resp) } async fn tunnel(host_port: String) -> Result<(), Box> { let mut parts = host_port.split(':'); let host = parts.next().ok_or("Invalid host")?; let port = parts.next().ok_or("Invalid port")?.parse::()?; let mut stream = TcpStream::connect((host, port)).await?; let io = TokioIo::new(stream); let (sender, conn) = hyper::server::conn::Http::new() .serve_connection(io, service_fn(move |req| handle_request(req, src))) .with_upgrades(); tokio::spawn(conn); Ok(()) } #[tokio::main] async fn main() -> Result<(), Box> { let addr = ([127, 0, 0, 1], 3000).into(); let make_svc = make_service_fn(|conn: AddrStream| { let src = conn.remote_addr(); async move { Ok::<_, Infallible>(service_fn(move |req| handle_request(req, src))) } }); let server = Server::bind(&addr).serve(make_svc); println!("Listening on http://{{}}", addr); server.await?; Ok(()) } ``` -------------------------------- ### Manual Service Trait Implementation Source: https://github.com/hyperium/hyper/blob/master/examples/README.md Implements the `Service` trait manually for a struct, demonstrating how to manage shared state across requests using a counter. Useful for custom service logic. ```rust use hyper::service::{Service, make_service_fn}; use hyper::{Body, Request, Response, Server, StatusCode}; use std::cell::RefCell; use std::convert::Infallible; use std::rc::Rc; struct AppState { counter: RefCell, } struct App { state: Rc, } impl Service> for App { type Response = Response; type Error = Infallible; type Future = futures_util::future::Ready>; fn call(&self, _req: Request) -> Self::Future { let mut counter = self.state.counter.borrow_mut(); *counter += 1; let response = Response::new(Body::from(format!("Request count: {}", *counter))); futures_util::future::ready(Ok(response)) } } #[tokio::main] async fn main() -> Result<(), Box> { let state = Rc::new(AppState { counter: RefCell::new(0), }); let make_svc = make_service_fn(move |_| { let state = Rc::clone(&state); async move { Ok::<_, Infallible>(App { state }) } }); let addr = ([127, 0 0 1], 3000).into(); let server = Server::bind(&addr).serve(make_svc); println!("Listening on http://{{}}", addr); server.await?; Ok(()) } ``` -------------------------------- ### Commit Message Format Source: https://github.com/hyperium/hyper/blob/master/docs/COMMITS.md The standard format for commit messages includes a header, body, and footer. Ensure no line exceeds 100 characters. ```git ():