summaryrefslogtreecommitdiff
path: root/vendor/hyper-rustls/examples/server.rs
diff options
context:
space:
mode:
authormo khan <mo@mokhan.ca>2025-07-10 13:11:11 -0600
committermo khan <mo@mokhan.ca>2025-07-10 13:11:11 -0600
commit01959b16a21b22b5df5f16569c2a8e8f92beecef (patch)
tree32afa5d747c5466345c59ec52161a7cba3d6d755 /vendor/hyper-rustls/examples/server.rs
parentff30574117a996df332e23d1fb6f65259b316b5b (diff)
chore: vendor dependencies
Diffstat (limited to 'vendor/hyper-rustls/examples/server.rs')
-rw-r--r--vendor/hyper-rustls/examples/server.rs138
1 files changed, 138 insertions, 0 deletions
diff --git a/vendor/hyper-rustls/examples/server.rs b/vendor/hyper-rustls/examples/server.rs
new file mode 100644
index 00000000..8f7803fa
--- /dev/null
+++ b/vendor/hyper-rustls/examples/server.rs
@@ -0,0 +1,138 @@
+//! Simple HTTPS echo service based on hyper_util and rustls
+//!
+//! First parameter is the mandatory port to use.
+//! Certificate and private key are hardcoded to sample files.
+//! hyper will automatically use HTTP/2 if a client starts talking HTTP/2,
+//! otherwise HTTP/1.1 will be used.
+
+use std::net::{Ipv4Addr, SocketAddr};
+use std::sync::Arc;
+use std::{env, fs, io};
+
+use http::{Method, Request, Response, StatusCode};
+use http_body_util::{BodyExt, Full};
+use hyper::body::{Bytes, Incoming};
+use hyper::service::service_fn;
+use hyper_util::rt::{TokioExecutor, TokioIo};
+use hyper_util::server::conn::auto::Builder;
+use pki_types::{CertificateDer, PrivateKeyDer};
+use rustls::ServerConfig;
+use tokio::net::TcpListener;
+use tokio_rustls::TlsAcceptor;
+
+fn main() {
+ // Serve an echo service over HTTPS, with proper error handling.
+ if let Err(e) = run_server() {
+ eprintln!("FAILED: {}", e);
+ std::process::exit(1);
+ }
+}
+
+fn error(err: String) -> io::Error {
+ io::Error::new(io::ErrorKind::Other, err)
+}
+
+#[tokio::main]
+async fn run_server() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
+ // Set a process wide default crypto provider.
+ #[cfg(feature = "ring")]
+ let _ = rustls::crypto::ring::default_provider().install_default();
+ #[cfg(feature = "aws-lc-rs")]
+ let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
+
+ // First parameter is port number (optional, defaults to 1337)
+ let port = match env::args().nth(1) {
+ Some(ref p) => p.parse()?,
+ None => 1337,
+ };
+ let addr = SocketAddr::new(Ipv4Addr::LOCALHOST.into(), port);
+
+ // Load public certificate.
+ let certs = load_certs("examples/sample.pem")?;
+ // Load private key.
+ let key = load_private_key("examples/sample.rsa")?;
+
+ println!("Starting to serve on https://{}", addr);
+
+ // Create a TCP listener via tokio.
+ let incoming = TcpListener::bind(&addr).await?;
+
+ // Build TLS configuration.
+ let mut server_config = ServerConfig::builder()
+ .with_no_client_auth()
+ .with_single_cert(certs, key)
+ .map_err(|e| error(e.to_string()))?;
+ server_config.alpn_protocols = vec![b"h2".to_vec(), b"http/1.1".to_vec(), b"http/1.0".to_vec()];
+ let tls_acceptor = TlsAcceptor::from(Arc::new(server_config));
+
+ let service = service_fn(echo);
+
+ loop {
+ let (tcp_stream, _remote_addr) = incoming.accept().await?;
+
+ let tls_acceptor = tls_acceptor.clone();
+ tokio::spawn(async move {
+ let tls_stream = match tls_acceptor.accept(tcp_stream).await {
+ Ok(tls_stream) => tls_stream,
+ Err(err) => {
+ eprintln!("failed to perform tls handshake: {err:#}");
+ return;
+ }
+ };
+ if let Err(err) = Builder::new(TokioExecutor::new())
+ .serve_connection(TokioIo::new(tls_stream), service)
+ .await
+ {
+ eprintln!("failed to serve connection: {err:#}");
+ }
+ });
+ }
+}
+
+// Custom echo service, handling two different routes and a
+// catch-all 404 responder.
+async fn echo(req: Request<Incoming>) -> Result<Response<Full<Bytes>>, hyper::Error> {
+ let mut response = Response::new(Full::default());
+ match (req.method(), req.uri().path()) {
+ // Help route.
+ (&Method::GET, "/") => {
+ *response.body_mut() = Full::from("Try POST /echo\n");
+ }
+ // Echo service route.
+ (&Method::POST, "/echo") => {
+ *response.body_mut() = Full::from(
+ req.into_body()
+ .collect()
+ .await?
+ .to_bytes(),
+ );
+ }
+ // Catch-all 404.
+ _ => {
+ *response.status_mut() = StatusCode::NOT_FOUND;
+ }
+ };
+ Ok(response)
+}
+
+// Load public certificate from file.
+fn load_certs(filename: &str) -> io::Result<Vec<CertificateDer<'static>>> {
+ // Open certificate file.
+ let certfile = fs::File::open(filename)
+ .map_err(|e| error(format!("failed to open {}: {}", filename, e)))?;
+ let mut reader = io::BufReader::new(certfile);
+
+ // Load and return certificate.
+ rustls_pemfile::certs(&mut reader).collect()
+}
+
+// Load private key from file.
+fn load_private_key(filename: &str) -> io::Result<PrivateKeyDer<'static>> {
+ // Open keyfile.
+ let keyfile = fs::File::open(filename)
+ .map_err(|e| error(format!("failed to open {}: {}", filename, e)))?;
+ let mut reader = io::BufReader::new(keyfile);
+
+ // Load and return a single private key.
+ rustls_pemfile::private_key(&mut reader).map(|key| key.unwrap())
+}