Skip to content

Commit e19a299

Browse files
Gelbpunktcpu
authored andcommitted
Update hyper to 1.x and integrate with hyper-util
This updates the entire dependency stack to hyper 1.x and http 1.x. The tokio-runtime feature was removed since it no longer serves a purpose and tokio is a hard dependency. Since hyper 1.x removed the high-level server API that supported customizing the accept process of the server via an Accept trait, the acceptor in hyper-rustls is removed. The server example however was updated to showcase how rustls can be integrated with the low-level hyper 1.x API. Signed-off-by: Jens Reidel <[email protected]>
1 parent def00ca commit e19a299

File tree

10 files changed

+112
-406
lines changed

10 files changed

+112
-406
lines changed

Cargo.toml

+12-11
Original file line numberDiff line numberDiff line change
@@ -11,32 +11,33 @@ repository = "https://github.com/rustls/hyper-rustls"
1111
documentation = "https://docs.rs/hyper-rustls/"
1212

1313
[dependencies]
14-
http = "0.2"
15-
hyper = { version = "0.14", default-features = false, features = ["client"] }
14+
http = "1"
15+
hyper = { version = "1", default-features = false }
16+
hyper-util = { version = "0.1", default-features = false, features = ["client-legacy", "tokio"] }
1617
log = { version = "0.4.4", optional = true }
1718
pki-types = { package = "rustls-pki-types", version = "1" }
1819
rustls-native-certs = { version = "0.7", optional = true }
1920
rustls = { version = "0.22", default-features = false }
2021
tokio = "1.0"
2122
tokio-rustls = { version = "0.25", default-features = false }
23+
tower-service = "0.3"
2224
webpki-roots = { version = "0.26", optional = true }
2325
futures-util = { version = "0.3", default-features = false }
2426

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

3134
[features]
32-
default = ["native-tokio", "http1", "tls12", "logging", "acceptor", "ring"]
33-
acceptor = ["hyper/server", "ring", "tokio-runtime"]
34-
http1 = ["hyper/http1"]
35-
http2 = ["hyper/http2"]
36-
webpki-tokio = ["tokio-runtime", "webpki-roots"]
37-
native-tokio = ["tokio-runtime", "rustls-native-certs"]
35+
default = ["native-tokio", "http1", "tls12", "logging", "ring"]
36+
http1 = ["hyper-util/http1"]
37+
http2 = ["hyper-util/http2"]
38+
webpki-tokio = ["webpki-roots"]
39+
native-tokio = ["rustls-native-certs"]
3840
ring = ["rustls/ring"]
39-
tokio-runtime = ["hyper/runtime"]
4041
tls12 = ["tokio-rustls/tls12", "rustls/tls12"]
4142
logging = ["log", "tokio-rustls/logging", "rustls/logging"]
4243

@@ -48,7 +49,7 @@ required-features = ["native-tokio", "http1"]
4849
[[example]]
4950
name = "server"
5051
path = "examples/server.rs"
51-
required-features = ["tokio-runtime", "acceptor"]
52+
required-features = ["ring"]
5253

5354
[package.metadata.docs.rs]
5455
all-features = true

examples/client.rs

+10-5
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@
22
//!
33
//! First parameter is the mandatory URL to GET.
44
//! Second parameter is an optional path to CA store.
5-
use hyper::{body::to_bytes, client, Body, Uri};
5+
use http::Uri;
6+
use http_body_util::{BodyExt, Empty};
7+
use hyper::body::Bytes;
68
use hyper_rustls::ConfigBuilderExt;
9+
use hyper_util::{client::legacy::Client, rt::TokioExecutor};
710
use rustls::RootCertStore;
811

912
use std::str::FromStr;
@@ -68,7 +71,7 @@ async fn run_client() -> io::Result<()> {
6871
.build();
6972

7073
// Build the hyper client from the HTTPS connector.
71-
let client: client::Client<_, hyper::Body> = client::Client::builder().build(https);
74+
let client: Client<_, Empty<Bytes>> = Client::builder(TokioExecutor::new()).build(https);
7275

7376
// Prepare a chain of futures which sends a GET request, inspects
7477
// the returned headers, collects the whole body and prints it to
@@ -81,10 +84,12 @@ async fn run_client() -> io::Result<()> {
8184
println!("Status:\n{}", res.status());
8285
println!("Headers:\n{:#?}", res.headers());
8386

84-
let body: Body = res.into_body();
85-
let body = to_bytes(body)
87+
let body = res
88+
.into_body()
89+
.collect()
8690
.await
87-
.map_err(|e| error(format!("Could not get body: {:?}", e)))?;
91+
.map_err(|e| error(format!("Could not get body: {:?}", e)))?
92+
.to_bytes();
8893
println!("Body:\n{}", String::from_utf8_lossy(&body));
8994

9095
Ok(())

examples/server.rs

+57-27
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,25 @@
1-
//! Simple HTTPS echo service based on hyper-rustls
1+
//! Simple HTTPS echo service based on hyper_util and rustls
22
//!
33
//! First parameter is the mandatory port to use.
44
//! Certificate and private key are hardcoded to sample files.
55
//! hyper will automatically use HTTP/2 if a client starts talking HTTP/2,
66
//! otherwise HTTP/1.1 will be used.
77
8-
#![cfg(feature = "acceptor")]
9-
8+
use std::net::{Ipv4Addr, SocketAddr};
9+
use std::sync::Arc;
1010
use std::vec::Vec;
1111
use std::{env, fs, io};
1212

13-
use hyper::server::conn::AddrIncoming;
14-
use hyper::service::{make_service_fn, service_fn};
15-
use hyper::{Body, Method, Request, Response, Server, StatusCode};
16-
use hyper_rustls::TlsAcceptor;
13+
use http::{Method, Request, Response, StatusCode};
14+
use http_body_util::{BodyExt, Full};
15+
use hyper::body::{Bytes, Incoming};
16+
use hyper::service::service_fn;
17+
use hyper_util::rt::{TokioExecutor, TokioIo};
18+
use hyper_util::server::conn::auto::Builder;
1719
use pki_types::{CertificateDer, PrivateKeyDer};
20+
use rustls::ServerConfig;
21+
use tokio::net::TcpListener;
22+
use tokio_rustls::TlsAcceptor;
1823

1924
fn main() {
2025
// Serve an echo service over HTTPS, with proper error handling.
@@ -32,45 +37,70 @@ fn error(err: String) -> io::Error {
3237
async fn run_server() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
3338
// First parameter is port number (optional, defaults to 1337)
3439
let port = match env::args().nth(1) {
35-
Some(ref p) => p.to_owned(),
36-
None => "1337".to_owned(),
40+
Some(ref p) => p.parse()?,
41+
None => 1337,
3742
};
38-
let addr = format!("127.0.0.1:{}", port).parse()?;
43+
let addr = SocketAddr::new(Ipv4Addr::LOCALHOST.into(), port);
3944

4045
// Load public certificate.
4146
let certs = load_certs("examples/sample.pem")?;
4247
// Load private key.
4348
let key = load_private_key("examples/sample.rsa")?;
44-
// Build TLS configuration.
49+
50+
println!("Starting to serve on https://{}", addr);
4551

4652
// Create a TCP listener via tokio.
47-
let incoming = AddrIncoming::bind(&addr)?;
48-
let acceptor = TlsAcceptor::builder()
53+
let incoming = TcpListener::bind(&addr).await?;
54+
55+
// Build TLS configuration.
56+
let mut server_config = ServerConfig::builder()
57+
.with_no_client_auth()
4958
.with_single_cert(certs, key)
50-
.map_err(|e| error(format!("{}", e)))?
51-
.with_all_versions_alpn()
52-
.with_incoming(incoming);
53-
let service = make_service_fn(|_| async { Ok::<_, io::Error>(service_fn(echo)) });
54-
let server = Server::builder(acceptor).serve(service);
55-
56-
// Run the future, keep going until an error occurs.
57-
println!("Starting to serve on https://{}.", addr);
58-
server.await?;
59-
Ok(())
59+
.map_err(|e| error(e.to_string()))?;
60+
server_config.alpn_protocols = vec![b"h2".to_vec(), b"http/1.1".to_vec(), b"http/1.0".to_vec()];
61+
let tls_acceptor = TlsAcceptor::from(Arc::new(server_config));
62+
63+
let service = service_fn(echo);
64+
65+
loop {
66+
let (tcp_stream, _remote_addr) = incoming.accept().await?;
67+
68+
let tls_acceptor = tls_acceptor.clone();
69+
tokio::spawn(async move {
70+
let tls_stream = match tls_acceptor.accept(tcp_stream).await {
71+
Ok(tls_stream) => tls_stream,
72+
Err(err) => {
73+
eprintln!("failed to perform tls handshake: {err:#}");
74+
return;
75+
}
76+
};
77+
if let Err(err) = Builder::new(TokioExecutor::new())
78+
.serve_connection(TokioIo::new(tls_stream), service)
79+
.await
80+
{
81+
eprintln!("failed to serve connection: {err:#}");
82+
}
83+
});
84+
}
6085
}
6186

6287
// Custom echo service, handling two different routes and a
6388
// catch-all 404 responder.
64-
async fn echo(req: Request<Body>) -> Result<Response<Body>, hyper::Error> {
65-
let mut response = Response::new(Body::empty());
89+
async fn echo(req: Request<Incoming>) -> Result<Response<Full<Bytes>>, hyper::Error> {
90+
let mut response = Response::new(Full::default());
6691
match (req.method(), req.uri().path()) {
6792
// Help route.
6893
(&Method::GET, "/") => {
69-
*response.body_mut() = Body::from("Try POST /echo\n");
94+
*response.body_mut() = Full::from("Try POST /echo\n");
7095
}
7196
// Echo service route.
7297
(&Method::POST, "/echo") => {
73-
*response.body_mut() = req.into_body();
98+
*response.body_mut() = Full::from(
99+
req.into_body()
100+
.collect()
101+
.await?
102+
.to_bytes(),
103+
);
74104
}
75105
// Catch-all 404.
76106
_ => {

src/acceptor.rs

-169
This file was deleted.

0 commit comments

Comments
 (0)