summaryrefslogtreecommitdiff
path: root/vendor/hyper-util/examples
diff options
context:
space:
mode:
authormo khan <mo@mokhan.ca>2025-07-02 18:36:06 -0600
committermo khan <mo@mokhan.ca>2025-07-02 18:36:06 -0600
commit8cdfa445d6629ffef4cb84967ff7017654045bc2 (patch)
tree22f0b0907c024c78d26a731e2e1f5219407d8102 /vendor/hyper-util/examples
parent4351c74c7c5f97156bc94d3a8549b9940ac80e3f (diff)
chore: add vendor directory
Diffstat (limited to 'vendor/hyper-util/examples')
-rw-r--r--vendor/hyper-util/examples/client.rs37
-rw-r--r--vendor/hyper-util/examples/server.rs75
-rw-r--r--vendor/hyper-util/examples/server_graceful.rs64
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(())
+}