summaryrefslogtreecommitdiff
path: root/vendor/hyper-rustls/examples
diff options
context:
space:
mode:
authormo khan <mo@mokhan.ca>2025-07-10 17:49:29 -0600
committermo khan <mo@mokhan.ca>2025-07-10 17:49:29 -0600
commitef572ae666732e87a35417710669ce88233a754a (patch)
tree3cc32004dee9600014417d404dbe01ac0e1faca9 /vendor/hyper-rustls/examples
parent8417a15087cc6f42c77fe070011ac2207f8d852d (diff)
parent6721aaffa33894624c87a54f4ed10eccd3c080e5 (diff)
Merge branch 'entities' into 'main'
Use a static ACL file(s) to make authorization decisions See merge request gitlab-org/software-supply-chain-security/authorization/authzd!6
Diffstat (limited to 'vendor/hyper-rustls/examples')
-rw-r--r--vendor/hyper-rustls/examples/client.rs105
-rw-r--r--vendor/hyper-rustls/examples/openssl.cnf25
-rwxr-xr-xvendor/hyper-rustls/examples/refresh-certificates.sh56
-rw-r--r--vendor/hyper-rustls/examples/sample.pem79
-rw-r--r--vendor/hyper-rustls/examples/sample.rsa27
-rw-r--r--vendor/hyper-rustls/examples/server.rs138
6 files changed, 430 insertions, 0 deletions
diff --git a/vendor/hyper-rustls/examples/client.rs b/vendor/hyper-rustls/examples/client.rs
new file mode 100644
index 00000000..c45bc2a7
--- /dev/null
+++ b/vendor/hyper-rustls/examples/client.rs
@@ -0,0 +1,105 @@
+//! Simple HTTPS GET client based on hyper-rustls
+//!
+//! First parameter is the mandatory URL to GET.
+//! Second parameter is an optional path to CA store.
+use http::Uri;
+use http_body_util::{BodyExt, Empty};
+use hyper::body::Bytes;
+use hyper_rustls::ConfigBuilderExt;
+use hyper_util::{client::legacy::Client, rt::TokioExecutor};
+use rustls::RootCertStore;
+
+use std::str::FromStr;
+use std::{env, fs, io};
+
+fn main() {
+ // Send GET request and inspect result, with proper error handling.
+ if let Err(e) = run_client() {
+ 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_client() -> io::Result<()> {
+ // 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 target URL (mandatory).
+ let url = match env::args().nth(1) {
+ Some(ref url) => Uri::from_str(url).map_err(|e| error(format!("{}", e)))?,
+ None => {
+ println!("Usage: client <url> <ca_store>");
+ return Ok(());
+ }
+ };
+
+ // Second parameter is custom Root-CA store (optional, defaults to native cert store).
+ let mut ca = match env::args().nth(2) {
+ Some(ref path) => {
+ let f = fs::File::open(path)
+ .map_err(|e| error(format!("failed to open {}: {}", path, e)))?;
+ let rd = io::BufReader::new(f);
+ Some(rd)
+ }
+ None => None,
+ };
+
+ // Prepare the TLS client config
+ let tls = match ca {
+ Some(ref mut rd) => {
+ // Read trust roots
+ let certs = rustls_pemfile::certs(rd).collect::<Result<Vec<_>, _>>()?;
+ let mut roots = RootCertStore::empty();
+ roots.add_parsable_certificates(certs);
+ // TLS client config using the custom CA store for lookups
+ rustls::ClientConfig::builder()
+ .with_root_certificates(roots)
+ .with_no_client_auth()
+ }
+ // Default TLS client config with native roots
+ None => rustls::ClientConfig::builder()
+ .with_native_roots()?
+ .with_no_client_auth(),
+ };
+ // Prepare the HTTPS connector
+ let https = hyper_rustls::HttpsConnectorBuilder::new()
+ .with_tls_config(tls)
+ .https_or_http()
+ .enable_http1()
+ .build();
+
+ // Build the hyper client from the HTTPS connector.
+ let client: Client<_, Empty<Bytes>> = Client::builder(TokioExecutor::new()).build(https);
+
+ // Prepare a chain of futures which sends a GET request, inspects
+ // the returned headers, collects the whole body and prints it to
+ // stdout.
+ let fut = async move {
+ let res = client
+ .get(url)
+ .await
+ .map_err(|e| error(format!("Could not get: {:?}", e)))?;
+ println!("Status:\n{}", res.status());
+ println!("Headers:\n{:#?}", res.headers());
+
+ let body = res
+ .into_body()
+ .collect()
+ .await
+ .map_err(|e| error(format!("Could not get body: {:?}", e)))?
+ .to_bytes();
+ println!("Body:\n{}", String::from_utf8_lossy(&body));
+
+ Ok(())
+ };
+
+ fut.await
+}
diff --git a/vendor/hyper-rustls/examples/openssl.cnf b/vendor/hyper-rustls/examples/openssl.cnf
new file mode 100644
index 00000000..cda95b5a
--- /dev/null
+++ b/vendor/hyper-rustls/examples/openssl.cnf
@@ -0,0 +1,25 @@
+
+[ v3_end ]
+basicConstraints = critical,CA:false
+keyUsage = nonRepudiation, digitalSignature
+subjectKeyIdentifier = hash
+authorityKeyIdentifier = keyid:always,issuer:always
+subjectAltName = @alt_names
+
+[ v3_client ]
+basicConstraints = critical,CA:false
+keyUsage = nonRepudiation, digitalSignature
+extendedKeyUsage = critical, clientAuth
+subjectKeyIdentifier = hash
+authorityKeyIdentifier = keyid:always,issuer:always
+
+[ v3_inter ]
+subjectKeyIdentifier = hash
+extendedKeyUsage = critical, serverAuth, clientAuth
+basicConstraints = CA:true
+keyUsage = cRLSign, keyCertSign, digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment, keyAgreement, keyCertSign, cRLSign
+
+[ alt_names ]
+DNS.1 = testserver.com
+DNS.2 = second.testserver.com
+DNS.3 = localhost
diff --git a/vendor/hyper-rustls/examples/refresh-certificates.sh b/vendor/hyper-rustls/examples/refresh-certificates.sh
new file mode 100755
index 00000000..db98af73
--- /dev/null
+++ b/vendor/hyper-rustls/examples/refresh-certificates.sh
@@ -0,0 +1,56 @@
+#!/bin/sh
+
+set -xe
+
+openssl req -nodes \
+ -x509 \
+ -days 3650 \
+ -newkey rsa:4096 \
+ -keyout ca.key \
+ -out ca.cert \
+ -sha256 \
+ -batch \
+ -subj "/CN=ponytown RSA CA"
+
+openssl req -nodes \
+ -newkey rsa:3072 \
+ -keyout inter.key \
+ -out inter.req \
+ -sha256 \
+ -batch \
+ -subj "/CN=ponytown RSA level 2 intermediate"
+
+openssl req -nodes \
+ -newkey rsa:2048 \
+ -keyout end.key \
+ -out end.req \
+ -sha256 \
+ -batch \
+ -subj "/CN=testserver.com"
+
+openssl rsa \
+ -in end.key \
+ -out sample.rsa
+
+openssl x509 -req \
+ -in inter.req \
+ -out inter.cert \
+ -CA ca.cert \
+ -CAkey ca.key \
+ -sha256 \
+ -days 3650 \
+ -set_serial 123 \
+ -extensions v3_inter -extfile openssl.cnf
+
+openssl x509 -req \
+ -in end.req \
+ -out end.cert \
+ -CA inter.cert \
+ -CAkey inter.key \
+ -sha256 \
+ -days 2000 \
+ -set_serial 456 \
+ -extensions v3_end -extfile openssl.cnf
+
+cat end.cert inter.cert ca.cert > sample.pem
+rm *.key *.cert *.req
diff --git a/vendor/hyper-rustls/examples/sample.pem b/vendor/hyper-rustls/examples/sample.pem
new file mode 100644
index 00000000..50b24b45
--- /dev/null
+++ b/vendor/hyper-rustls/examples/sample.pem
@@ -0,0 +1,79 @@
+-----BEGIN CERTIFICATE-----
+MIIEADCCAmigAwIBAgICAcgwDQYJKoZIhvcNAQELBQAwLDEqMCgGA1UEAwwhcG9u
+eXRvd24gUlNBIGxldmVsIDIgaW50ZXJtZWRpYXRlMB4XDTIyMDcwNDE0MzA1OFoX
+DTI3MTIyNTE0MzA1OFowGTEXMBUGA1UEAwwOdGVzdHNlcnZlci5jb20wggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDL35qLQLIqswCmHJxyczYF2p0YxXCq
+gMvtRcKVElnifPMFrbGCY1aYBmhIiXPGRwhfythAtYfDQsrXFADZd52JPgZCR/u6
+DQMqKD2lcvFQkf7Kee/fNTOuQTQPh1XQx4ntxvicSATwEnuU28NwVnOU//Zzq2xn
+Q34gUQNHWp1pN+B1La7emm/Ucgs1/2hMxwCZYUnRoiUoRGXUSzZuWokDOstPNkjc
++AjHmxONgowogmL2jKN9BjBw/8psGoqEOjMO+Lb9iekOCzX4kqHaRUbTlbSAviQu
+2Q115xiZCBCZVtNE6DUG25buvpMSEXwpLd96nLywbrSCyueC7cd01/hpAgMBAAGj
+gb4wgbswDAYDVR0TAQH/BAIwADALBgNVHQ8EBAMCBsAwHQYDVR0OBBYEFHGnzC5Q
+A62Wmv4zfMk/kf/BxHevMEIGA1UdIwQ7MDmAFDMRUvwxXbYDBCxOdQ9xfBnNWUz0
+oR6kHDAaMRgwFgYDVQQDDA9wb255dG93biBSU0EgQ0GCAXswOwYDVR0RBDQwMoIO
+dGVzdHNlcnZlci5jb22CFXNlY29uZC50ZXN0c2VydmVyLmNvbYIJbG9jYWxob3N0
+MA0GCSqGSIb3DQEBCwUAA4IBgQBqKNIM/JBGRmGEopm5/WNKV8UoxKPA+2jR020t
+RumXMAnJEfhsivF+Zw/rDmSDpmts/3cIlesKi47f13q4Mfj1QytQUDrsuQEyRTrV
+Go6BOQQ4dkS+IqnIfSuue70wpvrZHhRHNFdFt9qM5wCLQokXlP988sEWUmyPPCbO
+1BEpwWcP1kx+PdY8NKOhMnfq2RfluI/m4MA4NxJqAWajAhIbDNbvP8Ov4a71HPa6
+b1q9qIQE1ut8KycTrm9K32bVbvMHvR/TPUue8W0VvV2rWTGol5TSNgEQb9w6Kyf7
+N5HlRl9kZB4K8ckWH/JVn0pYNBQPgwbcUbJ/jp6w+LHrh+UW75maOY+IGjVICud8
+6Rc5DZZ2+AAbXJQZ1HMPrw9SW/16Eh/A4CIEsvbu9J+7IoSzhgcKFzOCUojzzRSj
+iU7w/HsvpltmVCAZcZ/VARFbe1By2wXX2GSw2p2FVC8orXs76QyruPAVgSHCTVes
+zzBo6GLScO/3b6uAcPM3MHRGGvE=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIEnzCCAoegAwIBAgIBezANBgkqhkiG9w0BAQsFADAaMRgwFgYDVQQDDA9wb255
+dG93biBSU0EgQ0EwHhcNMjIwNzA0MTQzMDU4WhcNMzIwNzAxMTQzMDU4WjAsMSow
+KAYDVQQDDCFwb255dG93biBSU0EgbGV2ZWwgMiBpbnRlcm1lZGlhdGUwggGiMA0G
+CSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCsTkd2SKiy3yy20lygOhKfOySo3qpq
+TZVrpW11vQ58+6EcetXRnzIIK0HyhPmZrv9XKPpQclJvfY9jADNtu2CSj/v15OSB
+Love3GzmXSZz2A8QUZBPWx6HczDG1hFGzrCZPKzpeLnFD1LPsKCUkUOHl1acyy24
+DaCacQJPzPQWbMhbGmYRlDNb+2R2K6UKMAEVe4IOTv2aSIKDGLI+xlaBXYAJj48L
+//9eNmR3bMP3kkNKOKaaBk8vnYxKpZ+8ZHeHTmYWR9x1ZoMcbA9lKUwRpKAjY5JJ
+NVZMDmjlVQVvvBrvhgz/zgXtfuaQCryZ0f1sEY/zXhdealo3fGVomeoniD4XwA1c
+oaUFkbo5IM5HU/pXyAGRerDyhYLgRqQZMIRauvKRPN3jLsPOEQ0+gnXUUTr/YGIE
+KY3/Axg4P3hzZCFqJ5IgkgWZr/dKr9p/0cxSUGHTVcpEFOlkKIIIdRuR7Ng5sJml
+u7PAMWt6T+x02ORs1/WkyP7LyPQmuugYTicCAwEAAaNeMFwwHQYDVR0OBBYEFDMR
+UvwxXbYDBCxOdQ9xfBnNWUz0MCAGA1UdJQEB/wQWMBQGCCsGAQUFBwMBBggrBgEF
+BQcDAjAMBgNVHRMEBTADAQH/MAsGA1UdDwQEAwIB/jANBgkqhkiG9w0BAQsFAAOC
+AgEAYzqmX+cNPgVD2HWgbeimUraTpI9JP5P4TbOHWmaJKecoy3Hwr71xyAOGiVXL
+urk1ZZe8n++GwuDEgRajN3HO9LR1Pu9qVIzTYIsz0ORRQHxujnF7CxK/I/vrIgde
+pddUdHNS0Y0g8J1emH9BgoD8a2YsGX4iDY4S4hIGBbGvQp9z8U/uG1mViAmlXybM
+b8bf0dx0tEFUyu8jsQP6nFLY/HhkEcvU6SnOzZHRsFko6NE44VIsHLd2+LS2LCM/
+NfAoTzgvj41M3zQCZapaHZc9KXfdcCvEFaySKGfEZeQTUR5W0FHsF5I4NLGryf5L
+h3ENQ1tgBTO5WnqL/5rbgv6va9VionPM5sbEwAcancejnkVs3NoYPIPPgBFjaFmL
+hNTpT9H2owdZvEwNDChVS0b8ukNNd4cERtvy0Ohc3mk0LGN0ABzrud0fIqa51LMh
+0N3dkPkiZ4XYk4yLJ5EwCrCNNH50QkGCOWpInKIPeSYcALGgBDbCDLv6rV3oSKrV
+tHCZQwXVKKgU4AQu7hlHBwJ61cH44ksydOidW3MNq1kDIp7ST8s7gVrItNgFnG+L
+Jpo270riwSUlWDY4hXw5Ff5lE+bWCmFyyOkLevDkD9v8M4HdwEVvafYYwn75fCIS
+5OnpSeIB08kKqCtW1WBwki0rYJjWqdzI7Z1MQ/AyScAKiGM=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIEsDCCApgCCQCfkxy3a+AgNjANBgkqhkiG9w0BAQsFADAaMRgwFgYDVQQDDA9w
+b255dG93biBSU0EgQ0EwHhcNMjIwNzA0MTQzMDU3WhcNMzIwNzAxMTQzMDU3WjAa
+MRgwFgYDVQQDDA9wb255dG93biBSU0EgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4IC
+DwAwggIKAoICAQCj6nW8pnN50UsH2NjL97xZKxlXPe5ptXfvqXczMsw0vB3gI4xJ
+Tdmrnqo0K+VOH7vh+UXcOj2ZMY2ou6oDDK5Qpu9bvGPBIJH/rC1Ti2+u5Y4KTIUc
+jWAtzQJeFn8+oCMfskpLdtlWLRdAuwqNHjvxXdd2JnsX1Wid85U/rG2SNPLGjJAF
+xG7xzZC4VSO2WIXTGRMUkZfFc8fhWMjo3GaeF/qYjzfHDPWN/ll/7vfxyXJO/ohw
+FzpJSZtKmI+6PLxqB/oFrKfTDQUGzxjfHp187bI3eyUFMJsp18/tLYkLyxSWIg3o
+bq7ZVimHd1UG2Vb5Y+5pZkh22jmJ6bAa/kmNNwbsD+5vJhW1myGhmZSxkreYPWnS
+6ELrSMvbXccFfTYmdBlWsZx/zUVUzVCPe9jdJki2VXlicohqtvBQqe6LGGO37vvv
+Gwu1yzQ/rJy47rnaao7fSxqM8nsDjNR2Ev1v031QpEMWjfgUW0roW3H58RZSx+kU
+gzIS2CjJIqKxCp894FUQbC6r0wwAuKltl3ywz5qWkxY0O9bXS0YdEXiri5pdsWjr
+84shVVQwnoVD9539CLSdHZjlOCAzvSWHZH6ta2JZjUfYYz8cLyv2c2+y9BYrlvHw
+T7U7BqzngUk72gcRXd5+Onp+16gGxpGJqaxqj94Nh/yTUnr2Jd9YaXeFmQIDAQAB
+MA0GCSqGSIb3DQEBCwUAA4ICAQBzIRVRt3Yaw60tpkyz/i1xbKCbtC+HqYTEsXvZ
+RvZ5X1qyLAcmu4EW9RHXnlLiawDbES6lCMFfdBUK03Wis7socvoFUCBRW337F4z2
+IivHfIge4u+w5ouUKPzcpj6oeuR06tmNytYbno6l8tXJpm1eeO4KNZ0ZtodmyB5D
+yLrplFgxTdGGgyvxt8LoeLwGmPCyVt35x/Mz6x2lcq1+r7QJZ9sENhQYuA8UqHrw
+fmNoVIMXMEcPLcWtFl6nKTK9LrqAu1jgTBqGGZKRn5CYBBK3pNEGKiOIsZXDbyFS
+F59teFpJjyeJTbUbLxXDa15J6ExkHV9wFLEvfu/nzQzg8D9yzczSdbDkE2rrrL+s
+Q/H/pIXO/DesCWQ37VALn3B5gm9UBd5uogbSw8eamiwRFLQ0snP80pJQGJoTNn0P
+wrLLUf2gsKC2262igiA+imepm5wxbV9XGVZfHJgxCi5Zqrf6aWnjIqD2YtDvAHhs
+V8ZWN3QTjdnEcQbG0544rocoLNX/FzmyDgjfZKY5r6wt+FWNc/R4clkF+KxasxqB
+HdBs8j0lGV3ujvNXASLq9HI6VxZayrSfkR73hADCXIM/wzynKwMarvA4SXwYX9Pd
+cJ4+FMqrevPpamMHUsNndS0KfDTdjDp+TSBf87yiyRkD1Ri4ePslyfNvRyv3Xs7k
+47YFzA==
+-----END CERTIFICATE-----
diff --git a/vendor/hyper-rustls/examples/sample.rsa b/vendor/hyper-rustls/examples/sample.rsa
new file mode 100644
index 00000000..aec53472
--- /dev/null
+++ b/vendor/hyper-rustls/examples/sample.rsa
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEAy9+ai0CyKrMAphyccnM2BdqdGMVwqoDL7UXClRJZ4nzzBa2x
+gmNWmAZoSIlzxkcIX8rYQLWHw0LK1xQA2XediT4GQkf7ug0DKig9pXLxUJH+ynnv
+3zUzrkE0D4dV0MeJ7cb4nEgE8BJ7lNvDcFZzlP/2c6tsZ0N+IFEDR1qdaTfgdS2u
+3ppv1HILNf9oTMcAmWFJ0aIlKERl1Es2blqJAzrLTzZI3PgIx5sTjYKMKIJi9oyj
+fQYwcP/KbBqKhDozDvi2/YnpDgs1+JKh2kVG05W0gL4kLtkNdecYmQgQmVbTROg1
+BtuW7r6TEhF8KS3fepy8sG60gsrngu3HdNf4aQIDAQABAoIBAFTehqVFj2W7EqAT
+9QSn9WtGcHNpbddsunfRvIj2FLj2LuzEO8r9s4Sh1jOsFKgL1e6asJ9vck7UtUAH
+sbrV0pzZVx2sfZwb4p9gFRmU2eQigqCjVjnjGdqGhjeYrR62kjKLy96zFGskJpH3
+UkqnkoIKc/v+9qeeLxkg4G6JyFGOFHJAZEraxoGydJk9n/yBEZ/+3W7JUJaGOUNU
+M7BYsCS2VOJr+cCqmCk1j8NvYvWWxTPsIXgGJl4EOoskzlzJnYLdh9fPFZu3uOIx
+hpm3DBNp6X+qXf1lmx9EdpyeXKpLFIgJM7+nw2uWzxW7XMlRERi+5Tprc/pjrqUq
+gpfyvMkCgYEA909QcJpS3qHoWyxGbI1zosVIZXdnj8L+GF/2kEQEU5iEYT+2M1U+
+gCPLr49gNwkD1FdBSCy+Fw20zi35jGmxNwhgp4V94CGYzqwQzpnvgIRBMiAIoEwI
+CD5/t34DZ/82u8Gb7UYVrzOD54rJ628Q+tJEJak3TqoShbvcxJC/rXMCgYEA0wmO
+SRoxrBE3rFzNQkqHbMHLe9LksW9YSIXdMBjq4DhzQEwI0YgPLajXnsLurqHaJrQA
+JPtYkqiJkV7rvJLBo5wxwU+O2JKKa2jcMwuCZ4hOg5oBfK6ES9QJZUL7kDe2vsWy
+rL+rnxJheUjDPBTopGHuuc9Nogid35CE0wy7S7MCgYArxB+KLeVofOKv79/uqgHC
+1oL/Yegz6uAo1CLAWSki2iTjSPEnmHhdGPic8xSl6LSCyYZGDZT+Y3CR5FT7YmD4
+SkVAoEEsfwWZ3Z2D0n4uEjmvczfTlmD9hIH5qRVVPDcldxfvH64KuWUofslJHvi0
+Sq3AtHeTNknc3Ogu6SbivQKBgQC4ZAsMWHS6MTkBwvwdRd1Z62INyNDFL9JlW4FN
+uxfN3cTlkwnJeiY48OOk9hFySDzBwFi3910Gl3fLqrIyy8+hUqIuk4LuO+vxuWdc
+uluwdmqTlgZimGFDl/q1nXcMJYHo4fgh9D7R+E9ul2Luph43MtJRS447W2gFpNJJ
+TUCA/QKBgQC07GFP2BN74UvL12f+FpZvE/UFtWnSZ8yJSq8oYpIbhmoF5EUF+XdA
+E2y3l1cvmDJFo4RNZl+IQIbHACR3y1XOnh4/B9fMEsVQHK3x8exPk1vAk687bBG8
+TVDmdP52XEKHplcVoYKvGzw/wsObLAGyIbJ00t1VPU+7guTPsc+H/w==
+-----END RSA PRIVATE KEY-----
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())
+}