Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update hyper to 1.x and integrate with hyper-util #232

Merged
merged 2 commits into from
Jan 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 13 additions & 12 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "hyper-rustls"
version = "0.25.0"
version = "0.26.0"
edition = "2021"
rust-version = "1.63"
license = "Apache-2.0 OR ISC OR MIT"
Expand All @@ -11,32 +11,33 @@ repository = "https://github.com/rustls/hyper-rustls"
documentation = "https://docs.rs/hyper-rustls/"

[dependencies]
http = "0.2"
hyper = { version = "0.14", default-features = false, features = ["client"] }
http = "1"
hyper = { version = "1", default-features = false }
hyper-util = { version = "0.1", default-features = false, features = ["client-legacy", "tokio"] }
log = { version = "0.4.4", optional = true }
pki-types = { package = "rustls-pki-types", version = "1" }
rustls-native-certs = { version = "0.7", optional = true }
rustls = { version = "0.22", default-features = false }
tokio = "1.0"
tokio-rustls = { version = "0.25", default-features = false }
tower-service = "0.3"
webpki-roots = { version = "0.26", optional = true }
futures-util = { version = "0.3", default-features = false }

[dev-dependencies]
hyper = { version = "0.14", features = ["full"] }
http-body-util = "0.1"
hyper-util = { version = "0.1", default-features = false, features = ["server-auto"] }
rustls = { version = "0.22", default-features = false, features = ["tls12"] }
rustls-pemfile = "2"
tokio = { version = "1.0", features = ["io-std", "macros", "net", "rt-multi-thread"] }

[features]
default = ["native-tokio", "http1", "tls12", "logging", "acceptor", "ring"]
acceptor = ["hyper/server", "ring", "tokio-runtime"]
http1 = ["hyper/http1"]
http2 = ["hyper/http2"]
webpki-tokio = ["tokio-runtime", "webpki-roots"]
native-tokio = ["tokio-runtime", "rustls-native-certs"]
default = ["native-tokio", "http1", "tls12", "logging", "ring"]
http1 = ["hyper-util/http1"]
http2 = ["hyper-util/http2"]
webpki-tokio = ["webpki-roots"]
native-tokio = ["rustls-native-certs"]
ring = ["rustls/ring"]
tokio-runtime = ["hyper/runtime"]
tls12 = ["tokio-rustls/tls12", "rustls/tls12"]
logging = ["log", "tokio-rustls/logging", "rustls/logging"]

Expand All @@ -48,7 +49,7 @@ required-features = ["native-tokio", "http1"]
[[example]]
name = "server"
path = "examples/server.rs"
required-features = ["tokio-runtime", "acceptor"]
required-features = ["ring"]

[package.metadata.docs.rs]
all-features = true
Expand Down
15 changes: 10 additions & 5 deletions examples/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@
//!
//! First parameter is the mandatory URL to GET.
//! Second parameter is an optional path to CA store.
use hyper::{body::to_bytes, client, Body, Uri};
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;
Expand Down Expand Up @@ -68,7 +71,7 @@ async fn run_client() -> io::Result<()> {
.build();

// Build the hyper client from the HTTPS connector.
let client: client::Client<_, hyper::Body> = client::Client::builder().build(https);
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
Expand All @@ -81,10 +84,12 @@ async fn run_client() -> io::Result<()> {
println!("Status:\n{}", res.status());
println!("Headers:\n{:#?}", res.headers());

let body: Body = res.into_body();
let body = to_bytes(body)
let body = res
.into_body()
.collect()
.await
.map_err(|e| error(format!("Could not get body: {:?}", e)))?;
.map_err(|e| error(format!("Could not get body: {:?}", e)))?
.to_bytes();
println!("Body:\n{}", String::from_utf8_lossy(&body));

Ok(())
Expand Down
84 changes: 57 additions & 27 deletions examples/server.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
//! Simple HTTPS echo service based on hyper-rustls
//! 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.

#![cfg(feature = "acceptor")]

use std::net::{Ipv4Addr, SocketAddr};
use std::sync::Arc;
use std::vec::Vec;
use std::{env, fs, io};

use hyper::server::conn::AddrIncoming;
use hyper::service::{make_service_fn, service_fn};
use hyper::{Body, Method, Request, Response, Server, StatusCode};
use hyper_rustls::TlsAcceptor;
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.
Expand All @@ -32,45 +37,70 @@ fn error(err: String) -> io::Error {
async fn run_server() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
// First parameter is port number (optional, defaults to 1337)
let port = match env::args().nth(1) {
Some(ref p) => p.to_owned(),
None => "1337".to_owned(),
Some(ref p) => p.parse()?,
None => 1337,
};
let addr = format!("127.0.0.1:{}", port).parse()?;
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")?;
// Build TLS configuration.

println!("Starting to serve on https://{}", addr);

// Create a TCP listener via tokio.
let incoming = AddrIncoming::bind(&addr)?;
let acceptor = TlsAcceptor::builder()
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(format!("{}", e)))?
.with_all_versions_alpn()
.with_incoming(incoming);
let service = make_service_fn(|_| async { Ok::<_, io::Error>(service_fn(echo)) });
let server = Server::builder(acceptor).serve(service);

// Run the future, keep going until an error occurs.
println!("Starting to serve on https://{}.", addr);
server.await?;
Ok(())
.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<Body>) -> Result<Response<Body>, hyper::Error> {
let mut response = Response::new(Body::empty());
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() = Body::from("Try POST /echo\n");
*response.body_mut() = Full::from("Try POST /echo\n");
}
// Echo service route.
(&Method::POST, "/echo") => {
*response.body_mut() = req.into_body();
*response.body_mut() = Full::from(
req.into_body()
.collect()
.await?
.to_bytes(),
);
}
// Catch-all 404.
_ => {
Expand Down
169 changes: 0 additions & 169 deletions src/acceptor.rs

This file was deleted.

Loading