actix-web: add rustls 0.23

This commit is contained in:
asonix 2024-05-12 18:31:29 -05:00
parent 07ad115185
commit 4fbb1ce2f8
5 changed files with 113 additions and 7 deletions

View File

@ -5,6 +5,10 @@
### Added ### Added
- Add `unicode` crate feature (on-by-default) to switch between `regex` and `regex-lite` as a trade-off between full unicode support and binary size. - Add `unicode` crate feature (on-by-default) to switch between `regex` and `regex-lite` as a trade-off between full unicode support and binary size.
- Add `rustls-0_23` crate feature.
- Add `HttpServer::{bind_rustls_0_23, listen_rustls_0_23}()` builder methods.
- Add `HttpServer::tls_handshake_timeout` builder method for `rustls-0_22` and `rustls-0_23`
### Changed ### Changed

View File

@ -27,6 +27,7 @@ features = [
"rustls-0_20", "rustls-0_20",
"rustls-0_21", "rustls-0_21",
"rustls-0_22", "rustls-0_22",
"rustls-0_23",
"compress-brotli", "compress-brotli",
"compress-gzip", "compress-gzip",
"compress-zstd", "compress-zstd",
@ -71,6 +72,8 @@ rustls-0_20 = ["http2", "actix-http/rustls-0_20", "actix-tls/accept", "actix-tls
rustls-0_21 = ["http2", "actix-http/rustls-0_21", "actix-tls/accept", "actix-tls/rustls-0_21"] rustls-0_21 = ["http2", "actix-http/rustls-0_21", "actix-tls/accept", "actix-tls/rustls-0_21"]
# TLS via Rustls v0.22 # TLS via Rustls v0.22
rustls-0_22 = ["http2", "actix-http/rustls-0_22", "actix-tls/accept", "actix-tls/rustls-0_22"] rustls-0_22 = ["http2", "actix-http/rustls-0_22", "actix-tls/accept", "actix-tls/rustls-0_22"]
# TLS via Rustls v0.23
rustls-0_23 = ["http2", "actix-http/rustls-0_23", "actix-tls/accept", "actix-tls/rustls-0_23"]
# Full unicode support # Full unicode support
unicode = ["dep:regex", "actix-router/unicode"] unicode = ["dep:regex", "actix-router/unicode"]
@ -122,7 +125,7 @@ url = "2.1"
[dev-dependencies] [dev-dependencies]
actix-files = "0.6" actix-files = "0.6"
actix-test = { version = "0.1", features = ["openssl", "rustls-0_22"] } actix-test = { version = "0.1", features = ["openssl", "rustls-0_23"] }
awc = { version = "3", features = ["openssl"] } awc = { version = "3", features = ["openssl"] }
brotli = "3.3.3" brotli = "3.3.3"
@ -137,7 +140,7 @@ rustls-pemfile = "2"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
static_assertions = "1" static_assertions = "1"
tls-openssl = { package = "openssl", version = "0.10.55" } tls-openssl = { package = "openssl", version = "0.10.55" }
tls-rustls = { package = "rustls", version = "0.22" } tls-rustls = { package = "rustls", version = "0.23" }
tokio = { version = "1.24.2", features = ["rt-multi-thread", "macros"] } tokio = { version = "1.24.2", features = ["rt-multi-thread", "macros"] }
zstd = "0.13" zstd = "0.13"

View File

@ -64,7 +64,10 @@
//! - `compress-gzip` - gzip and deflate content encoding compression support (enabled by default) //! - `compress-gzip` - gzip and deflate content encoding compression support (enabled by default)
//! - `compress-zstd` - zstd content encoding compression support (enabled by default) //! - `compress-zstd` - zstd content encoding compression support (enabled by default)
//! - `openssl` - HTTPS support via `openssl` crate, supports `HTTP/2` //! - `openssl` - HTTPS support via `openssl` crate, supports `HTTP/2`
//! - `rustls` - HTTPS support via `rustls` crate, supports `HTTP/2` //! - `rustls` - HTTPS support via `rustls` 0.20 crate, supports `HTTP/2`
//! - `rustls-0_21` - HTTPS support via `rustls` 0.21 crate, supports `HTTP/2`
//! - `rustls-0_22` - HTTPS support via `rustls` 0.22 crate, supports `HTTP/2`
//! - `rustls-0_23` - HTTPS support via `rustls` 0.23 crate, supports `HTTP/2`
//! - `secure-cookies` - secure cookies support //! - `secure-cookies` - secure cookies support
#![deny(rust_2018_idioms, nonstandard_style)] #![deny(rust_2018_idioms, nonstandard_style)]

View File

@ -12,6 +12,7 @@ use std::{
feature = "rustls-0_20", feature = "rustls-0_20",
feature = "rustls-0_21", feature = "rustls-0_21",
feature = "rustls-0_22", feature = "rustls-0_22",
feature = "rustls-0_23",
))] ))]
use actix_http::TlsAcceptorConfig; use actix_http::TlsAcceptorConfig;
use actix_http::{body::MessageBody, Extensions, HttpService, KeepAlive, Request, Response}; use actix_http::{body::MessageBody, Extensions, HttpService, KeepAlive, Request, Response};
@ -242,7 +243,13 @@ where
/// time, the connection is closed. /// time, the connection is closed.
/// ///
/// By default, the handshake timeout is 3 seconds. /// By default, the handshake timeout is 3 seconds.
#[cfg(any(feature = "openssl", feature = "rustls-0_20", feature = "rustls-0_21"))] #[cfg(any(
feature = "openssl",
feature = "rustls-0_20",
feature = "rustls-0_21",
feature = "rustls-0_22",
feature = "rustls-0_23",
))]
pub fn tls_handshake_timeout(self, dur: Duration) -> Self { pub fn tls_handshake_timeout(self, dur: Duration) -> Self {
self.config self.config
.lock() .lock()
@ -270,6 +277,10 @@ where
/// Rustls v0.20. /// Rustls v0.20.
/// - `actix_tls::accept::rustls_0_21::TlsStream<actix_web::rt::net::TcpStream>` when using /// - `actix_tls::accept::rustls_0_21::TlsStream<actix_web::rt::net::TcpStream>` when using
/// Rustls v0.21. /// Rustls v0.21.
/// - `actix_tls::accept::rustls_0_22::TlsStream<actix_web::rt::net::TcpStream>` when using
/// Rustls v0.22.
/// - `actix_tls::accept::rustls_0_23::TlsStream<actix_web::rt::net::TcpStream>` when using
/// Rustls v0.23.
/// - `actix_web::rt::net::TcpStream` when no encryption is used. /// - `actix_web::rt::net::TcpStream` when no encryption is used.
/// ///
/// See the `on_connect` example for additional details. /// See the `on_connect` example for additional details.
@ -466,6 +477,25 @@ where
Ok(self) Ok(self)
} }
/// Resolves socket address(es) and binds server to created listener(s) for TLS connections
/// using Rustls v0.23.
///
/// See [`bind()`](Self::bind()) for more details on `addrs` argument.
///
/// ALPN protocols "h2" and "http/1.1" are added to any configured ones.
#[cfg(feature = "rustls-0_23")]
pub fn bind_rustls_0_23<A: net::ToSocketAddrs>(
mut self,
addrs: A,
config: actix_tls::accept::rustls_0_23::reexports::ServerConfig,
) -> io::Result<Self> {
let sockets = bind_addrs(addrs, self.backlog)?;
for lst in sockets {
self = self.listen_rustls_0_23_inner(lst, config.clone())?;
}
Ok(self)
}
/// Resolves socket address(es) and binds server to created listener(s) for TLS connections /// Resolves socket address(es) and binds server to created listener(s) for TLS connections
/// using OpenSSL. /// using OpenSSL.
/// ///
@ -775,6 +805,72 @@ where
Ok(self) Ok(self)
} }
/// Binds to existing listener for accepting incoming TLS connection requests using Rustls
/// v0.23.
///
/// See [`listen()`](Self::listen) for more details on the `lst` argument.
///
/// ALPN protocols "h2" and "http/1.1" are added to any configured ones.
#[cfg(feature = "rustls-0_23")]
pub fn listen_rustls_0_23(
self,
lst: net::TcpListener,
config: actix_tls::accept::rustls_0_23::reexports::ServerConfig,
) -> io::Result<Self> {
self.listen_rustls_0_23_inner(lst, config)
}
#[cfg(feature = "rustls-0_23")]
fn listen_rustls_0_23_inner(
mut self,
lst: net::TcpListener,
config: actix_tls::accept::rustls_0_23::reexports::ServerConfig,
) -> io::Result<Self> {
let factory = self.factory.clone();
let cfg = self.config.clone();
let addr = lst.local_addr().unwrap();
self.sockets.push(Socket {
addr,
scheme: "https",
});
let on_connect_fn = self.on_connect_fn.clone();
self.builder =
self.builder
.listen(format!("actix-web-service-{}", addr), lst, move || {
let c = cfg.lock().unwrap();
let host = c.host.clone().unwrap_or_else(|| format!("{}", addr));
let svc = HttpService::build()
.keep_alive(c.keep_alive)
.client_request_timeout(c.client_request_timeout)
.client_disconnect_timeout(c.client_disconnect_timeout);
let svc = if let Some(handler) = on_connect_fn.clone() {
svc.on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext))
} else {
svc
};
let fac = factory()
.into_factory()
.map_err(|err| err.into().error_response());
let acceptor_config = match c.tls_handshake_timeout {
Some(dur) => TlsAcceptorConfig::default().handshake_timeout(dur),
None => TlsAcceptorConfig::default(),
};
svc.finish(map_config(fac, move |_| {
AppConfig::new(true, host.clone(), addr)
}))
.rustls_0_23_with_config(config.clone(), acceptor_config)
})?;
Ok(self)
}
/// Binds to existing listener for accepting incoming TLS connection requests using OpenSSL. /// Binds to existing listener for accepting incoming TLS connection requests using OpenSSL.
/// ///
/// See [`listen()`](Self::listen) for more details on the `lst` argument. /// See [`listen()`](Self::listen) for more details on the `lst` argument.

View File

@ -1,6 +1,6 @@
#[cfg(feature = "openssl")] #[cfg(feature = "openssl")]
extern crate tls_openssl as openssl; extern crate tls_openssl as openssl;
#[cfg(feature = "rustls-0_22")] #[cfg(feature = "rustls-0_23")]
extern crate tls_rustls as rustls; extern crate tls_rustls as rustls;
use std::{ use std::{
@ -704,7 +704,7 @@ async fn test_brotli_encoding_large_openssl() {
srv.stop().await; srv.stop().await;
} }
#[cfg(feature = "rustls-0_22")] #[cfg(feature = "rustls-0_23")]
mod plus_rustls { mod plus_rustls {
use std::io::BufReader; use std::io::BufReader;
@ -740,7 +740,7 @@ mod plus_rustls {
.map(char::from) .map(char::from)
.collect::<String>(); .collect::<String>();
let srv = actix_test::start_with(actix_test::config().rustls_0_22(tls_config()), || { let srv = actix_test::start_with(actix_test::config().rustls_0_23(tls_config()), || {
App::new().service(web::resource("/").route(web::to(|bytes: Bytes| async { App::new().service(web::resource("/").route(web::to(|bytes: Bytes| async {
// echo decompressed request body back in response // echo decompressed request body back in response
HttpResponse::Ok() HttpResponse::Ok()