### Complete Client-Server Example over Unix Sockets Source: https://context7.com/softprops/hyperlocal/llms.txt Demonstrates a full client-server interaction using Unix domain sockets. Includes setting up a server, a client making a request, and verifying the response. ```rust use http_body_util::{BodyExt, Full}; use hyper::{body::Bytes, service::service_fn, Response}; use hyper_util::{client::legacy::Client, rt::TokioIo}; use hyperlocal::{UnixClientExt, UnixConnector, Uri}; use std::{error::Error, fs, path::Path}; use tokio::net::UnixListener; const PHRASE: &str = "Hello from Unix socket!"; #[tokio::main] async fn main() -> Result<(), Box> { let path = Path::new("/tmp/hyperlocal.sock"); if path.exists() { fs::remove_file(path)?; } // Create the server handler let svc_fn = service_fn(|_req| async { Ok::<_, hyper::Error>(Response::new(PHRASE.to_string())) }); let listener = UnixListener::bind(path)?; // Spawn server in background task let server_task = tokio::spawn(async move { let (stream, _) = listener.accept().await.expect("accept failed"); let io = TokioIo::new(stream); hyper::server::conn::http1::Builder::new() .serve_connection(io, svc_fn) .await .expect("serve failed"); }); // Create client and make request let client: Client> = Client::unix(); let url = Uri::new(path, "/").into(); let mut response = client.get(url).await?; let mut bytes = Vec::new(); while let Some(frame_result) = response.frame().await { let frame = frame_result?; if let Some(segment) = frame.data_ref() { bytes.extend(segment.iter().as_slice()); } } let body = String::from_utf8(bytes)?; println!("Response: {}", body); assert_eq!(PHRASE, body); server_task.await?; Ok(()) } ``` -------------------------------- ### Testing Unix Socket Servers with curl Source: https://context7.com/softprops/hyperlocal/llms.txt Demonstrates how to test Unix domain socket servers using curl with the --unix-socket option. Includes examples for basic requests, custom paths, and POST requests with data. ```bash # Start the server first, then test with curl curl --unix-socket /tmp/hyperlocal.sock http://localhost/ # Expected output: # It's a Unix system. I know this. # Test with custom paths curl --unix-socket /tmp/hyperlocal.sock http://localhost/api/status curl --unix-socket /tmp/hyperlocal.sock -X POST http://localhost/api/data -d '{"key":"value"}' ``` -------------------------------- ### Simplified Unix Client Construction with UnixClientExt Source: https://context7.com/softprops/hyperlocal/llms.txt Use the `UnixClientExt` trait's `unix()` method for convenient HTTP client creation over Unix domain sockets without manual connector setup. ```rust use http_body_util::{BodyExt, Full}; use hyper::body::Bytes; use hyper_util::client::legacy::Client; use hyperlocal::{UnixClientExt, UnixConnector, Uri}; use std::error::Error; use tokio::io::{self, AsyncWriteExt as _}; #[tokio::main] async fn main() -> Result<(), Box> { // Create a Unix domain socket client with default settings let client: Client> = Client::unix(); // Build the URI for the Unix socket and path let url = Uri::new("/tmp/hyperlocal.sock", "/").into(); // Make a GET request let mut response = client.get(url).await?; // Stream the response body to stdout while let Some(frame_result) = response.frame().await { let frame = frame_result?; if let Some(segment) = frame.data_ref() { io::stdout().write_all(segment.iter().as_slice()).await?; } } Ok(()) } ``` -------------------------------- ### Low-Level Server with Hyper Builder Source: https://context7.com/softprops/hyperlocal/llms.txt Use Hyper's http1::Builder directly with tokio::net::UnixListener for fine-grained server configuration. Handles incoming requests and spawns a task for each connection. ```rust use http_body_util::Full; use hyper::{body::Bytes, service::service_fn, Response, Request, body::Incoming}; use hyper_util::rt::TokioIo; use std::{error::Error, fs, path::Path}; use tokio::net::UnixListener; async fn handle_request(req: Request) -> Result, hyper::Error> { // Access request method, path, headers, etc. let path = req.uri().path().to_string(); let response_body = format!("Received request for: {}", path); Ok(Response::new(response_body)) } #[tokio::main] async fn main() -> Result<(), Box> { let path = Path::new("/tmp/hyperlocal.sock"); if path.exists() { fs::remove_file(path)?; } let listener = UnixListener::bind(path)?; loop { let (stream, _addr) = listener.accept().await?; let io = TokioIo::new(stream); // Create a service function from the handler let svc_fn = service_fn(handle_request); // Spawn a task for each connection tokio::spawn(async move { if let Err(err) = hyper::server::conn::http1::Builder::new() .keep_alive(false) // Recommended for Unix sockets on macOS .serve_connection(io, svc_fn) .await { eprintln!("Error serving connection: {}", err); } }); } } ``` -------------------------------- ### Serve HTTP Requests over Unix Domain Sockets Source: https://context7.com/softprops/hyperlocal/llms.txt Use the `UnixListenerExt` trait's `serve()` method to easily accept connections and respond to HTTP requests on a Unix domain socket. ```rust use std::{error::Error, fs, path::Path}; use hyper::Response; use tokio::net::UnixListener; use hyperlocal::UnixListenerExt; #[tokio::main] async fn main() -> Result<(), Box> { let path = Path::new("/tmp/hyperlocal.sock"); // Clean up existing socket file if present if path.exists() { fs::remove_file(path)?; } // Bind to the Unix socket let listener = UnixListener::bind(path)?; println!("Listening for connections at {}.", path.display()); // Serve requests using the extension trait // The outer closure creates a handler for each connection // The inner closure handles each request on that connection listener .serve(|| { println!("Accepted connection."); |_request| async { let body = "It's a Unix system. I know this.\n".to_string(); Ok::<_, hyper::Error>(Response::new(body)) } }) .await?; Ok(()) } ``` -------------------------------- ### Convert to hyper::Uri Source: https://github.com/softprops/hyperlocal/blob/main/CHANGELOG.md Demonstrates how to convert a hyperlocal Uri to a hyper::Uri. This is useful for compatibility with Hyper's newer naming conventions. ```rust let uri: hyper:Uri = hyperlocal::Uri( "path/to/server.sock", "/foo/bar?baz=boom" ).into(); ``` -------------------------------- ### Build Hyper Client with UnixConnector Source: https://context7.com/softprops/hyperlocal/llms.txt Implement Hyper's `Service` trait using `UnixConnector` for fine-grained control over Hyper client builder configuration when connecting via Unix domain sockets. ```rust use http_body_util::Full; use hyper::body::Bytes; use hyper_util::{client::legacy::Client, rt::TokioExecutor}; use hyperlocal::UnixConnector; // Create a connector for Unix domain sockets let connector = UnixConnector; // Build a Hyper client with custom configuration let client: Client> = Client::builder(TokioExecutor::new()) .pool_idle_timeout(std::time::Duration::from_secs(30)) .build(connector); ``` -------------------------------- ### Construct Unix Domain Socket URI Source: https://context7.com/softprops/hyperlocal/llms.txt Use the `Uri` struct to create URIs for Unix domain sockets. The socket path is hex-encoded in the host part of the resulting `hyper::Uri`. ```rust use hyper::Uri as HyperUri; use hyperlocal::Uri; // Create a URI targeting a Unix socket at /tmp/hyperlocal.sock // with the path "/" on that socket let uri: HyperUri = Uri::new("/tmp/hyperlocal.sock", "/").into(); // Create a URI with a custom path and query string let api_uri: HyperUri = Uri::new("/var/run/docker.sock", "/containers/json?all=true").into(); // The socket path is hex-encoded in the host portion // unix://2f746d702f687970726c6f63616c2e736f636b:0/ ``` -------------------------------- ### UnixStream for Hyper Compatibility Source: https://context7.com/softprops/hyperlocal/llms.txt UnixStream wraps tokio::net::UnixStream, implementing Hyper's Read/Write and Tokio's AsyncRead/AsyncWrite traits. It supports vectored writes for efficient I/O and integrates with Hyper via the Connection trait. ```rust use hyperlocal::UnixStream; use hyper_util::client::legacy::connect::Connection; // UnixStream is automatically used by UnixConnector internally // It supports vectored writes for efficient I/O operations // The stream implements Connection trait for Hyper compatibility // When using UnixConnector, UnixStream handles the actual data transfer: // - Implements poll_read/poll_write for async I/O // - Supports vectored writes via poll_write_vectored // - Provides Connection::connected() for Hyper integration ``` -------------------------------- ### Test Hyperlocal Server with Curl Source: https://github.com/softprops/hyperlocal/blob/main/README.md Use curl to send a request to a running hyperlocal server via its Unix domain socket. ```sh $ curl --unix-socket /tmp/hyperlocal.sock localhost It's a Unix system. I know this. ``` -------------------------------- ### Add Hyperlocal Dependency to Cargo.toml Source: https://github.com/softprops/hyperlocal/blob/main/README.md Include the hyperlocal crate in your project's dependencies by adding this to your Cargo.toml file. ```toml [dependencies] hyperlocal = "0.9" ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.