Repository: actix/actix-web (language: rust)

Issue:
rustls v0.21 upgrade
## Steps to Reproduce (for bugs)

<!--- Provide a link to a live example, or an unambiguous set of steps to -->
<!--- reproduce this bug. Include code to reproduce, if relevant -->

When  version of rustls upgraded from 0.20.8 to 0.21.2:
```
= note: `ServerConfig` and `ServerConfig` have similar names, but are actually distinct types
note: `ServerConfig` is defined in crate `rustls`
   --> /home/ferrislav/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rustls-0.21.2/src/server/server_conn.rs:199:1
    |
199 | pub struct ServerConfig {
    | ^^^^^^^^^^^^^^^^^^^^^^^
note: `ServerConfig` is defined in crate `rustls`
   --> /home/ferrislav/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rustls-0.20.8/src/server/server_conn.rs:201:1
    |
201 | pub struct ServerConfig {
    | ^^^^^^^^^^^^^^^^^^^^^^^
    = note: perhaps two different versions of crate `rustls` are being used?
note: method defined here
   --> /home/s/.cargo/registry/src/index.crates.io-6f17d22bba15001f/actix-web-4.3.1/src/server.rs:386:12
    |
386 |     pub fn bind_rustls<A: net::ToSocketAddrs>(
    |            ^^^^^^^^^^^
```

- Rust Version (I.e, output of `rustc -V`): 1.7.0
- Actix Web Version: 4



Discussion / hints:
Yep I've come across this also;

![image](https://github.com/actix/actix-web/assets/16097639/506da4e3-cb12-4a09-8bb2-2af1dd17cea3)

https://github.com/actix/actix-web/blob/0e8ed50e3a7ac93d94e6c1c6603d0048e1f33fb8/actix-web/src/server.rs#L19

Temporary workaround is to downgrade rustls to 0.20.8

...I don't have the Rust skillz to create a PR yet :)
Some kind of non-breaking rustls v0.21 is in the works. For now, just use rustls v0.20. You shouldn't see anything missing really.
@robjtede Is there any way I could help make this update happen?

`rustls` `v0.20` depends on https://github.com/briansmith/webpki which is not regularly maintained and has [a vulnerability](https://rustsec.org/advisories/RUSTSEC-2023-0052.html)


Another issue with using rustls v0.20 is that it does not have support for IP addresses in SANs and thus it's not possible to connect to peers named with IP addresses
Minimum viable feature support is being prioritized given the recent RUSTSEC report. Changes made will be strictly backwards-compatible so will require users to enable new features and change methods called.

Fix patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index f1220201735..fdd6f0f9abd 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -56,6 +56,7 @@ jobs:
         if: matrix.version.name != 'stable'
         run: |
           cargo update -p=clap --precise=4.3.24
+          cargo update -p=clap_lex --precise=0.5.0
 
       - name: check minimal
         run: cargo ci-check-min
diff --git a/Cargo.toml b/Cargo.toml
index 65e3c6ae88f..58fd96935a2 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -14,6 +14,11 @@ members = [
     "awc",
 ]
 
+[workspace.package]
+license = "MIT OR Apache-2.0"
+edition = "2021"
+rust-version = "1.68"
+
 [profile.dev]
 # Disabling debug info speeds up builds a bunch and we don't rely on it for debugging that much.
 debug = 0
diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md
index 0dedd2c7496..7078adb7e20 100644
--- a/actix-http/CHANGES.md
+++ b/actix-http/CHANGES.md
@@ -4,6 +4,8 @@
 
 ### Added
 
+- Add `rustls-0_20` crate feature.
+- Add `{H1Service, H2Service, HttpService}::rustls_021()` and `HttpService::rustls_021_with_config()` service constructors.
 - Add `body::to_body_limit()` function.
 - Add `body::BodyLimitExceeded` error type.
 
diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml
index 6909b785fda..61fba4bce00 100644
--- a/actix-http/Cargo.toml
+++ b/actix-http/Cargo.toml
@@ -15,8 +15,9 @@ categories = [
     "web-programming::http-server",
     "web-programming::websocket",
 ]
-license = "MIT OR Apache-2.0"
-edition = "2021"
+license.workspace = true
+edition.workspace = true
+rust-version.workspace = true
 
 [package.metadata.docs.rs]
 # features that docs.rs will build with
@@ -43,15 +44,21 @@ ws = [
 # TLS via OpenSSL
 openssl = ["actix-tls/accept", "actix-tls/openssl"]
 
-# TLS via Rustls
-rustls = ["actix-tls/accept", "actix-tls/rustls"]
+# TLS via Rustls v0.20
+rustls = ["rustls-0_20"]
+
+# TLS via Rustls v0.20
+rustls-0_20 = ["actix-tls/accept", "actix-tls/rustls-0_20"]
+
+# TLS via Rustls v0.21
+rustls-0_21 = ["actix-tls/accept", "actix-tls/rustls-0_21"]
 
 # Compression codecs
 compress-brotli = ["__compress", "brotli"]
 compress-gzip   = ["__compress", "flate2"]
 compress-zstd   = ["__compress", "zstd"]
 
-# Internal (PRIVATE!) features used to aid testing and cheking feature status.
+# Internal (PRIVATE!) features used to aid testing and checking feature status.
 # Don't rely on these whatsoever. They are semver-exempt and may disappear at anytime.
 __compress = []
 
@@ -91,7 +98,7 @@ rand = { version = "0.8", optional = true }
 sha1 = { version = "0.10", optional = true }
 
 # openssl/rustls
-actix-tls = { version = "3", default-features = false, optional = true }
+actix-tls = { version = "3.1", default-features = false, optional = true }
 
 # compress-*
 brotli = { version = "3.3.3", optional = true }
@@ -101,7 +108,7 @@ zstd = { version = "0.12", optional = true }
 [dev-dependencies]
 actix-http-test = { version = "3", features = ["openssl"] }
 actix-server = "2"
-actix-tls = { version = "3", features = ["openssl"] }
+actix-tls = { version = "3.1", features = ["openssl"] }
 actix-web = "4"
 
 async-stream = "0.3"
@@ -118,12 +125,16 @@ serde = { version = "1.0", features = ["derive"] }
 serde_json = "1.0"
 static_assertions = "1"
 tls-openssl = { package = "openssl", version = "0.10.55" }
-tls-rustls = { package = "rustls", version = "0.20" }
+tls-rustls_021 = { package = "rustls", version = "0.21" }
 tokio = { version = "1.24.2", features = ["net", "rt", "macros"] }
 
 [[example]]
 name = "ws"
-required-features = ["ws", "rustls"]
+required-features = ["ws", "rustls-0_21"]
+
+[[example]]
+name = "tls_rustls"
+required-features = ["http2", "rustls-0_21"]
 
 [[bench]]
 name = "response-body-compression"
diff --git a/actix-http/examples/tls_rustls.rs b/actix-http/examples/tls_rustls.rs
new file mode 100644
index 00000000000..fbb55c6a4f2
--- /dev/null
+++ b/actix-http/examples/tls_rustls.rs
@@ -0,0 +1,73 @@
+//! Demonstrates TLS configuration (via Rustls) for HTTP/1.1 and HTTP/2 connections.
+//!
+//! Test using cURL:
+//!
+//! ```console
+//! $ curl --insecure https://127.0.0.1:8443
+//! Hello World!
+//! Protocol: HTTP/2.0
+//!
+//! $ curl --insecure --http1.1 https://127.0.0.1:8443
+//! Hello World!
+//! Protocol: HTTP/1.1
+//! ```
+
+extern crate tls_rustls_021 as rustls;
+
+use std::io;
+
+use actix_http::{Error, HttpService, Request, Response};
+use actix_utils::future::ok;
+
+#[actix_rt::main]
+async fn main() -> io::Result<()> {
+    env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
+
+    tracing::info!("starting HTTP server at https://127.0.0.1:8443");
+
+    actix_server::Server::build()
+        .bind("echo", ("127.0.0.1", 8443), || {
+            HttpService::build()
+                .finish(|req: Request| {
+                    let body = format!(
+                        "Hello World!\n\
+                        Protocol: {:?}",
+                        req.head().version
+                    );
+                    ok::<_, Error>(Response::ok().set_body(body))
+                })
+                .rustls_021(rustls_config())
+        })?
+        .run()
+        .await
+}
+
+fn rustls_config() -> rustls::ServerConfig {
+    let cert = rcgen::generate_simple_self_signed(vec!["localhost".to_owned()]).unwrap();
+    let cert_file = cert.serialize_pem().unwrap();
+    let key_file = cert.serialize_private_key_pem();
+
+    let cert_file = &mut io::BufReader::new(cert_file.as_bytes());
+    let key_file = &mut io::BufReader::new(key_file.as_bytes());
+
+    let cert_chain = rustls_pemfile::certs(cert_file)
+        .unwrap()
+        .into_iter()
+        .map(rustls::Certificate)
+        .collect();
+    let mut keys = rustls_pemfile::pkcs8_private_keys(key_file).unwrap();
+
+    let mut config = rustls::ServerConfig::builder()
+        .with_safe_defaults()
+        .with_no_client_auth()
+        .with_single_cert(cert_chain, rustls::PrivateKey(keys.remove(0)))
+        .unwrap();
+
+    const H1_ALPN: &[u8] = b"http/1.1";
+    const H2_ALPN: &[u8] = b"h2";
+
+    config.alpn_protocols.push(H2_ALPN.to_vec());
+    config.alpn_protocols.push(H1_ALPN.to_vec());
+
+    config
+}
diff --git a/actix-http/examples/ws.rs b/actix-http/examples/ws.rs
index 6af6d509589..241175ae2f7 100644
--- a/actix-http/examples/ws.rs
+++ b/actix-http/examples/ws.rs
@@ -1,7 +1,7 @@
 //! Sets up a WebSocket server over TCP and TLS.
 //! Sends a heartbeat message every 4 seconds but does not respond to any incoming frames.
 
-extern crate tls_rustls as rustls;
+extern crate tls_rustls_021 as rustls;
 
 use std::{
     io,
@@ -28,7 +28,9 @@ async fn main() -> io::Result<()> {
             HttpService::build().h1(handler).tcp()
         })?
         .bind("tls", ("127.0.0.1", 8443), || {
-            HttpService::build().finish(handler).rustls(tls_config())
+            HttpService::build()
+                .finish(handler)
+                .rustls_021(tls_config())
         })?
         .run()
         .await
diff --git a/actix-http/src/h1/service.rs b/actix-http/src/h1/service.rs
index fbda7138e73..3b27e3db561 100644
--- a/actix-http/src/h1/service.rs
+++ b/actix-http/src/h1/service.rs
@@ -152,13 +152,13 @@ mod openssl {
     }
 }
 
-#[cfg(feature = "rustls")]
-mod rustls {
+#[cfg(feature = "rustls-0_20")]
+mod rustls_020 {
     use std::io;
 
     use actix_service::ServiceFactoryExt as _;
     use actix_tls::accept::{
-        rustls::{reexports::ServerConfig, Acceptor, TlsStream},
+        rustls_0_20::{reexports::ServerConfig, Acceptor, TlsStream},
         TlsError,
     };
 
@@ -188,7 +188,7 @@ mod rustls {
         U::Error: fmt::Display + Into<Response<BoxBody>>,
         U::InitError: fmt::Debug,
     {
-        /// Create Rustls based service.
+        /// Create Rustls v0.20 based service.
         pub fn rustls(
             self,
             config: ServerConfig,
@@ -213,6 +213,67 @@ mod rustls {
     }
 }
 
+#[cfg(feature = "rustls-0_21")]
+mod rustls_021 {
+    use std::io;
+
+    use actix_service::ServiceFactoryExt as _;
+    use actix_tls::accept::{
+        rustls_0_21::{reexports::ServerConfig, Acceptor, TlsStream},
+        TlsError,
+    };
+
+    use super::*;
+
+    impl<S, B, X, U> H1Service<TlsStream<TcpStream>, S, B, X, U>
+    where
+        S: ServiceFactory<Request, Config = ()>,
+        S::Future: 'static,
+        S::Error: Into<Response<BoxBody>>,
+        S::InitError: fmt::Debug,
+        S::Response: Into<Response<B>>,
+
+        B: MessageBody,
+
+        X: ServiceFactory<Request, Config = (), Response = Request>,
+        X::Future: 'static,
+        X::Error: Into<Response<BoxBody>>,
+        X::InitError: fmt::Debug,
+
+        U: ServiceFactory<
+            (Request, Framed<TlsStream<TcpStream>, Codec>),
+            Config = (),
+            Response = (),
+        >,
+        U::Future: 'static,
+        U::Error: fmt::Display + Into<Response<BoxBody>>,
+        U::InitError: fmt::Debug,
+    {
+        /// Create Rustls v0.21 based service.
+        pub fn rustls_021(
+            self,
+            config: ServerConfig,
+        ) -> impl ServiceFactory<
+            TcpStream,
+            Config = (),
+            Response = (),
+            Error = TlsError<io::Error, DispatchError>,
+            InitError = (),
+        > {
+            Acceptor::new(config)
+                .map_init_err(|_| {
+                    unreachable!("TLS acceptor service factory does not error on init")
+                })
+                .map_err(TlsError::into_service_error)
+                .map(|io: TlsStream<TcpStream>| {
+                    let peer_addr = io.get_ref().0.peer_addr().ok();
+                    (io, peer_addr)
+                })
+                .and_then(self.map_err(TlsError::Service))
+        }
+    }
+}
+
 impl<T, S, B, X, U> H1Service<T, S, B, X, U>
 where
     S: ServiceFactory<Request, Config = ()>,
diff --git a/actix-http/src/h2/service.rs b/actix-http/src/h2/service.rs
index 3f742135a9f..0ae7ea682db 100644
--- a/actix-http/src/h2/service.rs
+++ b/actix-http/src/h2/service.rs
@@ -140,8 +140,8 @@ mod openssl {
     }
 }
 
-#[cfg(feature = "rustls")]
-mod rustls {
+#[cfg(feature = "rustls-0_20")]
+mod rustls_020 {
     use std::io;
 
     use actix_service::ServiceFactoryExt as _;
@@ -162,7 +162,7 @@ mod rustls {
 
         B: MessageBody + 'static,
     {
-        /// Create Rustls based service.
+        /// Create Rustls v0.20 based service.
         pub fn rustls(
             self,
             mut config: ServerConfig,
@@ -191,6 +191,57 @@ mod rustls {
     }
 }
 
+#[cfg(feature = "rustls-0_21")]
+mod rustls_021 {
+    use std::io;
+
+    use actix_service::ServiceFactoryExt as _;
+    use actix_tls::accept::{
+        rustls_0_21::{reexports::ServerConfig, Acceptor, TlsStream},
+        TlsError,
+    };
+
+    use super::*;
+
+    impl<S, B> H2Service<TlsStream<TcpStream>, S, B>
+    where
+        S: ServiceFactory<Request, Config = ()>,
+        S::Future: 'static,
+        S::Error: Into<Response<BoxBody>> + 'static,
+        S::Response: Into<Response<B>> + 'static,
+        <S::Service as Service<Request>>::Future: 'static,
+
+        B: MessageBody + 'static,
+    {
+        /// Create Rustls v0.21 based service.
+        pub fn rustls_021(
+            self,
+            mut config: ServerConfig,
+        ) -> impl ServiceFactory<
+            TcpStream,
+            Config = (),
+            Response = (),
+            Error = TlsError<io::Error, DispatchError>,
+            InitError = S::InitError,
+        > {
+            let mut protos = vec![b"h2".to_vec()];
+            protos.extend_from_slice(&config.alpn_protocols);
+            config.alpn_protocols = protos;
+
+            Acceptor::new(config)
+                .map_init_err(|_| {
+                    unreachable!("TLS acceptor service factory does not error on init")
+                })
+                .map_err(TlsError::into_service_error)
+                .map(|io: TlsStream<TcpStream>| {
+                    let peer_addr = io.get_ref().0.peer_addr().ok();
+                    (io, peer_addr)
+                })
+                .and_then(self.map_err(TlsError::Service))
+        }
+    }
+}
+
 impl<T, S, B> ServiceFactory<(T, Option<net::SocketAddr>)> for H2Service<T, S, B>
 where
     T: AsyncRead + AsyncWrite + Unpin + 'static,
diff --git a/actix-http/src/lib.rs b/actix-http/src/lib.rs
index 8b755f2f428..382295fbc5c 100644
--- a/actix-http/src/lib.rs
+++ b/actix-http/src/lib.rs
@@ -58,7 +58,7 @@ pub mod ws;
 
 #[allow(deprecated)]
 pub use self::payload::PayloadStream;
-#[cfg(any(feature = "openssl", feature = "rustls"))]
+#[cfg(any(feature = "openssl", feature = "rustls-0_20", feature = "rustls-0_21"))]
 pub use self::service::TlsAcceptorConfig;
 pub use self::{
     builder::HttpServiceBuilder,
diff --git a/actix-http/src/service.rs b/actix-http/src/service.rs
index e118d836178..bb0fda8c457 100644
--- a/actix-http/src/service.rs
+++ b/actix-http/src/service.rs
@@ -241,13 +241,13 @@ where
 }
 
 /// Configuration options used when accepting TLS connection.
-#[cfg(any(feature = "openssl", feature = "rustls"))]
+#[cfg(any(feature = "openssl", feature = "rustls-0_20", feature = "rustls-0_21"))]
 #[derive(Debug, Default)]
 pub struct TlsAcceptorConfig {
     pub(crate) handshake_timeout: Option<std::time::Duration>,
 }
 
-#[cfg(any(feature = "openssl", feature = "rustls"))]
+#[cfg(any(feature = "openssl", feature = "rustls", feature = "rustls-0_21"))]
 impl TlsAcceptorConfig {
     /// Set TLS handshake timeout duration.
     pub fn handshake_timeout(self, dur: std::time::Duration) -> Self {
@@ -352,8 +352,8 @@ mod openssl {
     }
 }
 
-#[cfg(feature = "rustls")]
-mod rustls {
+#[cfg(feature = "rustls-0_20")]
+mod rustls_020 {
     use std::io;
 
     use actix_service::ServiceFactoryExt as _;
@@ -448,6 +448,102 @@ mod rustls {
     }
 }
 
+#[cfg(feature = "rustls-0_21")]
+mod rustls_021 {
+    use std::io;
+
+    use actix_service::ServiceFactoryExt as _;
+    use actix_tls::accept::{
+        rustls_0_21::{reexports::ServerConfig, Acceptor, TlsStream},
+        TlsError,
+    };
+
+    use super::*;
+
+    impl<S, B, X, U> HttpService<TlsStream<TcpStream>, S, B, X, U>
+    where
+        S: ServiceFactory<Request, Config = ()>,
+        S::Future: 'static,
+        S::Error: Into<Response<BoxBody>> + 'static,
+        S::InitError: fmt::Debug,
+        S::Response: Into<Response<B>> + 'static,
+        <S::Service as Service<Request>>::Future: 'static,
+
+        B: MessageBody + 'static,
+
+        X: ServiceFactory<Request, Config = (), Response = Request>,
+        X::Future: 'static,
+        X::Error: Into<Response<BoxBody>>,
+        X::InitError: fmt::Debug,
+
+        U: ServiceFactory<
+            (Request, Framed<TlsStream<TcpStream>, h1::Codec>),
+            Config = (),
+            Response = (),
+        >,
+        U::Future: 'static,
+        U::Error: fmt::Display + Into<Response<BoxBody>>,
+        U::InitError: fmt::Debug,
+    {
+        /// Create Rustls based service.
+        pub fn rustls_021(
+            self,
+            config: ServerConfig,
+        ) -> impl ServiceFactory<
+            TcpStream,
+            Config = (),
+            Response = (),
+            Error = TlsError<io::Error, DispatchError>,
+            InitError = (),
+        > {
+            self.rustls_021_with_config(config, TlsAcceptorConfig::default())
+        }
+
+        /// Create Rustls based service with custom TLS acceptor configuration.
+        pub fn rustls_021_with_config(
+            self,
+            mut config: ServerConfig,
+            tls_acceptor_config: TlsAcceptorConfig,
+        ) -> impl ServiceFactory<
+            TcpStream,
+            Config = (),
+            Response = (),
+            Error = TlsError<io::Error, DispatchError>,
+            InitError = (),
+        > {
+            let mut protos = vec![b"h2".to_vec(), b"http/1.1".to_vec()];
+            protos.extend_from_slice(&config.alpn_protocols);
+            config.alpn_protocols = protos;
+
+            let mut acceptor = Acceptor::new(config);
+
+            if let Some(handshake_timeout) = tls_acceptor_config.handshake_timeout {
+                acceptor.set_handshake_timeout(handshake_timeout);
+            }
+
+            acceptor
+                .map_init_err(|_| {
+                    unreachable!("TLS acceptor service factory does not error on init")
+                })
+                .map_err(TlsError::into_service_error)
+                .and_then(|io: TlsStream<TcpStream>| async {
+                    let proto = if let Some(protos) = io.get_ref().1.alpn_protocol() {
+                        if protos.windows(2).any(|window| window == b"h2") {
+                            Protocol::Http2
+                        } else {
+                            Protocol::Http1
+                        }
+                    } else {
+                        Protocol::Http1
+                    };
+                    let peer_addr = io.get_ref().0.peer_addr().ok();
+                    Ok((io, proto, peer_addr))
+                })
+                .and_then(self.map_err(TlsError::Service))
+        }
+    }
+}
+
 impl<T, S, B, X, U> ServiceFactory<(T, Protocol, Option<net::SocketAddr>)>
     for HttpService<T, S, B, X, U>
 where
diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml
index 4322fb871e3..7dbaa2a296c 100644
--- a/actix-web/Cargo.toml
+++ b/actix-web/Cargo.toml
@@ -16,7 +16,8 @@ categories = [
 homepage = "https://actix.rs"
 repository = "https://github.com/actix/actix-web.git"
 license = "MIT OR Apache-2.0"
-edition = "2021"
+edition.workspace = true
+rust-version.workspace = true
 
 [package.metadata.docs.rs]
 # features that docs.rs will build with
diff --git a/awc/Cargo.toml b/awc/Cargo.toml
index daec84ab95e..2a09a52c48f 100644
--- a/awc/Cargo.toml
+++ b/awc/Cargo.toml
@@ -45,7 +45,7 @@ cookies = ["cookie"]
 # trust-dns as dns resolver
 trust-dns = ["trust-dns-resolver"]
 
-# Internal (PRIVATE!) features used to aid testing and cheking feature status.
+# Internal (PRIVATE!) features used to aid testing and checking feature status.
 # Don't rely on these whatsoever. They may disappear at anytime.
 __compress = []
 


Test patch:
diff --git a/actix-http/tests/test_rustls.rs b/actix-http/tests/test_rustls.rs
index 3d9a39cbd80..c94e579e5dd 100644
--- a/actix-http/tests/test_rustls.rs
+++ b/actix-http/tests/test_rustls.rs
@@ -1,7 +1,6 @@
-#![cfg(feature = "rustls")]
-#![allow(clippy::uninlined_format_args)]
+#![cfg(feature = "rustls-0_21")]
 
-extern crate tls_rustls as rustls;
+extern crate tls_rustls_021 as rustls;
 
 use std::{
     convert::Infallible,
@@ -21,7 +20,7 @@ use actix_http::{
 use actix_http_test::test_server;
 use actix_rt::pin;
 use actix_service::{fn_factory_with_config, fn_service};
-use actix_tls::connect::rustls::webpki_roots_cert_store;
+use actix_tls::connect::rustls_0_21::webpki_roots_cert_store;
 use actix_utils::future::{err, ok, poll_fn};
 use bytes::{Bytes, BytesMut};
 use derive_more::{Display, Error};
@@ -110,7 +109,7 @@ async fn h1() -> io::Result<()> {
     let srv = test_server(move || {
         HttpService::build()
             .h1(|_| ok::<_, Error>(Response::ok()))
-            .rustls(tls_config())
+            .rustls_021(tls_config())
     })
     .await;
 
@@ -124,7 +123,7 @@ async fn h2() -> io::Result<()> {
     let srv = test_server(move || {
         HttpService::build()
             .h2(|_| ok::<_, Error>(Response::ok()))
-            .rustls(tls_config())
+            .rustls_021(tls_config())
     })
     .await;
 
@@ -142,7 +141,7 @@ async fn h1_1() -> io::Result<()> {
                 assert_eq!(req.version(), Version::HTTP_11);
                 ok::<_, Error>(Response::ok())
             })
-            .rustls(tls_config())
+            .rustls_021(tls_config())
     })
     .await;
 
@@ -160,7 +159,7 @@ async fn h2_1() -> io::Result<()> {
                 assert_eq!(req.version(), Version::HTTP_2);
                 ok::<_, Error>(Response::ok())
             })
-            .rustls_with_config(
+            .rustls_021_with_config(
                 tls_config(),
                 TlsAcceptorConfig::default().handshake_timeout(Duration::from_secs(5)),
             )
@@ -181,7 +180,7 @@ async fn h2_body1() -> io::Result<()> {
                 let body = load_body(req.take_payload()).await?;
                 Ok::<_, Error>(Response::ok().set_body(body))
             })
-            .rustls(tls_config())
+            .rustls_021(tls_config())
     })
     .await;
 
@@ -207,7 +206,7 @@ async fn h2_content_length() {
                 ];
                 ok::<_, Infallible>(Response::new(statuses[indx]))
             })
-            .rustls(tls_config())
+            .rustls_021(tls_config())
     })
     .await;
 
@@ -279,7 +278,7 @@ async fn h2_headers() {
                 }
                 ok::<_, Infallible>(config.body(data.clone()))
             })
-            .rustls(tls_config())
+            .rustls_021(tls_config())
     })
     .await;
 
@@ -318,7 +317,7 @@ async fn h2_body2() {
     let mut srv = test_server(move || {
         HttpService::build()
             .h2(|_| ok::<_, Infallible>(Response::ok().set_body(STR)))
-            .rustls(tls_config())
+            .rustls_021(tls_config())
     })
     .await;
 
@@ -335,7 +334,7 @@ async fn h2_head_empty() {
     let mut srv = test_server(move || {
         HttpService::build()
             .finish(|_| ok::<_, Infallible>(Response::ok().set_body(STR)))
-            .rustls(tls_config())
+            .rustls_021(tls_config())
     })
     .await;
 
@@ -361,7 +360,7 @@ async fn h2_head_binary() {
     let mut srv = test_server(move || {
         HttpService::build()
             .h2(|_| ok::<_, Infallible>(Response::ok().set_body(STR)))
-            .rustls(tls_config())
+            .rustls_021(tls_config())
     })
     .await;
 
@@ -386,7 +385,7 @@ async fn h2_head_binary2() {
     let srv = test_server(move || {
         HttpService::build()
             .h2(|_| ok::<_, Infallible>(Response::ok().set_body(STR)))
-            .rustls(tls_config())
+            .rustls_021(tls_config())
     })
     .await;
 
@@ -412,7 +411,7 @@ async fn h2_body_length() {
                     Response::ok().set_body(SizedStream::new(STR.len() as u64, body)),
                 )
             })
-            .rustls(tls_config())
+            .rustls_021(tls_config())
     })
     .await;
 
@@ -436,7 +435,7 @@ async fn h2_body_chunked_explicit() {
                         .body(BodyStream::new(body)),
                 )
             })
-            .rustls(tls_config())
+            .rustls_021(tls_config())
     })
     .await;
 
@@ -465,7 +464,7 @@ async fn h2_response_http_error_handling() {
                     )
                 }))
             }))
-            .rustls(tls_config())
+            .rustls_021(tls_config())
     })
     .await;
 
@@ -495,7 +494,7 @@ async fn h2_service_error() {
     let mut srv = test_server(move || {
         HttpService::build()
             .h2(|_| err::<Response<BoxBody>, _>(BadRequest))
-            .rustls(tls_config())
+            .rustls_021(tls_config())
     })
     .await;
 
@@ -512,7 +511,7 @@ async fn h1_service_error() {
     let mut srv = test_server(move || {
         HttpService::build()
             .h1(|_| err::<Response<BoxBody>, _>(BadRequest))
-            .rustls(tls_config())
+            .rustls_021(tls_config())
     })
     .await;
 
@@ -535,7 +534,7 @@ async fn alpn_h1() -> io::Result<()> {
         config.alpn_protocols.push(CUSTOM_ALPN_PROTOCOL.to_vec());
         HttpService::build()
             .h1(|_| ok::<_, Error>(Response::ok()))
-            .rustls(config)
+            .rustls_021(config)
     })
     .await;
 
@@ -557,7 +556,7 @@ async fn alpn_h2() -> io::Result<()> {
         config.alpn_protocols.push(CUSTOM_ALPN_PROTOCOL.to_vec());
         HttpService::build()
             .h2(|_| ok::<_, Error>(Response::ok()))
-            .rustls(config)
+            .rustls_021(config)
     })
     .await;
 
@@ -583,7 +582,7 @@ async fn alpn_h2_1() -> io::Result<()> {
         config.alpn_protocols.push(CUSTOM_ALPN_PROTOCOL.to_vec());
         HttpService::build()
             .finish(|_| ok::<_, Error>(Response::ok()))
-            .rustls(config)
+            .rustls_021(config)
     })
     .await;