diff options
| author | mo khan <mo@mokhan.ca> | 2025-07-02 18:36:06 -0600 |
|---|---|---|
| committer | mo khan <mo@mokhan.ca> | 2025-07-02 18:36:06 -0600 |
| commit | 8cdfa445d6629ffef4cb84967ff7017654045bc2 (patch) | |
| tree | 22f0b0907c024c78d26a731e2e1f5219407d8102 /vendor/hyper-util/examples | |
| parent | 4351c74c7c5f97156bc94d3a8549b9940ac80e3f (diff) | |
chore: add vendor directory
Diffstat (limited to 'vendor/hyper-util/examples')
| -rw-r--r-- | vendor/hyper-util/examples/client.rs | 37 | ||||
| -rw-r--r-- | vendor/hyper-util/examples/server.rs | 75 | ||||
| -rw-r--r-- | vendor/hyper-util/examples/server_graceful.rs | 64 |
3 files changed, 176 insertions, 0 deletions
diff --git a/vendor/hyper-util/examples/client.rs b/vendor/hyper-util/examples/client.rs new file mode 100644 index 00000000..04defac0 --- /dev/null +++ b/vendor/hyper-util/examples/client.rs @@ -0,0 +1,37 @@ +use std::env; + +use http_body_util::Empty; +use hyper::Request; +use hyper_util::client::legacy::{connect::HttpConnector, Client}; + +#[tokio::main(flavor = "current_thread")] +async fn main() -> Result<(), Box<dyn std::error::Error>> { + let url = match env::args().nth(1) { + Some(url) => url, + None => { + eprintln!("Usage: client <url>"); + return Ok(()); + } + }; + + // HTTPS requires picking a TLS implementation, so give a better + // warning if the user tries to request an 'https' URL. + let url = url.parse::<hyper::Uri>()?; + if url.scheme_str() != Some("http") { + eprintln!("This example only works with 'http' URLs."); + return Ok(()); + } + + let client = Client::builder(hyper_util::rt::TokioExecutor::new()).build(HttpConnector::new()); + + let req = Request::builder() + .uri(url) + .body(Empty::<bytes::Bytes>::new())?; + + let resp = client.request(req).await?; + + eprintln!("{:?} {:?}", resp.version(), resp.status()); + eprintln!("{:#?}", resp.headers()); + + Ok(()) +} diff --git a/vendor/hyper-util/examples/server.rs b/vendor/hyper-util/examples/server.rs new file mode 100644 index 00000000..48806d80 --- /dev/null +++ b/vendor/hyper-util/examples/server.rs @@ -0,0 +1,75 @@ +//! This example runs a server that responds to any request with "Hello, world!" + +use std::{convert::Infallible, error::Error}; + +use bytes::Bytes; +use http::{header::CONTENT_TYPE, Request, Response}; +use http_body_util::{combinators::BoxBody, BodyExt, Full}; +use hyper::{body::Incoming, service::service_fn}; +use hyper_util::{ + rt::{TokioExecutor, TokioIo}, + server::conn::auto::Builder, +}; +use tokio::{net::TcpListener, task::JoinSet}; + +/// Function from an incoming request to an outgoing response +/// +/// This function gets turned into a [`hyper::service::Service`] later via +/// [`service_fn`]. Instead of doing this, you could also write a type that +/// implements [`hyper::service::Service`] directly and pass that in place of +/// writing a function like this and calling [`service_fn`]. +/// +/// This function could use [`Full`] as the body type directly since that's +/// the only type that can be returned in this case, but this uses [`BoxBody`] +/// anyway for demonstration purposes, since this is what's usually used when +/// writing a more complex webserver library. +async fn handle_request( + _request: Request<Incoming>, +) -> Result<Response<BoxBody<Bytes, Infallible>>, Infallible> { + let response = Response::builder() + .header(CONTENT_TYPE, "text/plain") + .body(Full::new(Bytes::from("Hello, world!\n")).boxed()) + .expect("values provided to the builder should be valid"); + + Ok(response) +} + +#[tokio::main(flavor = "current_thread")] +async fn main() -> Result<(), Box<dyn Error + Send + Sync + 'static>> { + let listen_addr = "127.0.0.1:8000"; + let tcp_listener = TcpListener::bind(listen_addr).await?; + println!("listening on http://{listen_addr}"); + + let mut join_set = JoinSet::new(); + loop { + let (stream, addr) = match tcp_listener.accept().await { + Ok(x) => x, + Err(e) => { + eprintln!("failed to accept connection: {e}"); + continue; + } + }; + + let serve_connection = async move { + println!("handling a request from {addr}"); + + let result = Builder::new(TokioExecutor::new()) + .serve_connection(TokioIo::new(stream), service_fn(handle_request)) + .await; + + if let Err(e) = result { + eprintln!("error serving {addr}: {e}"); + } + + println!("handled a request from {addr}"); + }; + + join_set.spawn(serve_connection); + } + + // If you add a method for breaking the above loop (i.e. graceful shutdown), + // then you may also want to wait for all existing connections to finish + // being served before terminating the program, which can be done like this: + // + // while let Some(_) = join_set.join_next().await {} +} diff --git a/vendor/hyper-util/examples/server_graceful.rs b/vendor/hyper-util/examples/server_graceful.rs new file mode 100644 index 00000000..bfb43a4b --- /dev/null +++ b/vendor/hyper-util/examples/server_graceful.rs @@ -0,0 +1,64 @@ +use bytes::Bytes; +use std::convert::Infallible; +use std::pin::pin; +use std::time::Duration; +use tokio::net::TcpListener; + +#[tokio::main(flavor = "current_thread")] +async fn main() -> Result<(), Box<dyn std::error::Error>> { + let listener = TcpListener::bind("127.0.0.1:8080").await?; + + let server = hyper_util::server::conn::auto::Builder::new(hyper_util::rt::TokioExecutor::new()); + let graceful = hyper_util::server::graceful::GracefulShutdown::new(); + let mut ctrl_c = pin!(tokio::signal::ctrl_c()); + + loop { + tokio::select! { + conn = listener.accept() => { + let (stream, peer_addr) = match conn { + Ok(conn) => conn, + Err(e) => { + eprintln!("accept error: {}", e); + tokio::time::sleep(Duration::from_secs(1)).await; + continue; + } + }; + eprintln!("incomming connection accepted: {}", peer_addr); + + let stream = hyper_util::rt::TokioIo::new(Box::pin(stream)); + + let conn = server.serve_connection_with_upgrades(stream, hyper::service::service_fn(|_| async move { + tokio::time::sleep(Duration::from_secs(5)).await; // emulate slow request + let body = http_body_util::Full::<Bytes>::from("Hello World!".to_owned()); + Ok::<_, Infallible>(http::Response::new(body)) + })); + + let conn = graceful.watch(conn.into_owned()); + + tokio::spawn(async move { + if let Err(err) = conn.await { + eprintln!("connection error: {}", err); + } + eprintln!("connection dropped: {}", peer_addr); + }); + }, + + _ = ctrl_c.as_mut() => { + drop(listener); + eprintln!("Ctrl-C received, starting shutdown"); + break; + } + } + } + + tokio::select! { + _ = graceful.shutdown() => { + eprintln!("Gracefully shutdown!"); + }, + _ = tokio::time::sleep(Duration::from_secs(10)) => { + eprintln!("Waited 10 seconds for graceful shutdown, aborting..."); + } + } + + Ok(()) +} |
