Skip to content

Commit

Permalink
actix-web: add rustls 0.23
Browse files Browse the repository at this point in the history
  • Loading branch information
asonix committed May 12, 2024
1 parent 07ad115 commit 4fbb1ce
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 7 deletions.
4 changes: 4 additions & 0 deletions actix-web/CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
### 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 `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

Expand Down
7 changes: 5 additions & 2 deletions actix-web/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ features = [
"rustls-0_20",
"rustls-0_21",
"rustls-0_22",
"rustls-0_23",
"compress-brotli",
"compress-gzip",
"compress-zstd",
Expand Down Expand Up @@ -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"]
# TLS via Rustls v0.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
unicode = ["dep:regex", "actix-router/unicode"]
Expand Down Expand Up @@ -122,7 +125,7 @@ url = "2.1"

[dev-dependencies]
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"] }

brotli = "3.3.3"
Expand All @@ -137,7 +140,7 @@ rustls-pemfile = "2"
serde = { version = "1.0", features = ["derive"] }
static_assertions = "1"
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"] }
zstd = "0.13"

Expand Down
5 changes: 4 additions & 1 deletion actix-web/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,10 @@
//! - `compress-gzip` - gzip and deflate 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`
//! - `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

#![deny(rust_2018_idioms, nonstandard_style)]
Expand Down
98 changes: 97 additions & 1 deletion actix-web/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use std::{
feature = "rustls-0_20",
feature = "rustls-0_21",
feature = "rustls-0_22",
feature = "rustls-0_23",
))]
use actix_http::TlsAcceptorConfig;
use actix_http::{body::MessageBody, Extensions, HttpService, KeepAlive, Request, Response};
Expand Down Expand Up @@ -242,7 +243,13 @@ where
/// time, the connection is closed.
///
/// 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 {
self.config
.lock()
Expand Down Expand Up @@ -270,6 +277,10 @@ where
/// Rustls v0.20.
/// - `actix_tls::accept::rustls_0_21::TlsStream<actix_web::rt::net::TcpStream>` when using
/// 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.
///
/// See the `on_connect` example for additional details.
Expand Down Expand Up @@ -466,6 +477,25 @@ where
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
/// using OpenSSL.
///
Expand Down Expand Up @@ -775,6 +805,72 @@ where
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.
///
/// See [`listen()`](Self::listen) for more details on the `lst` argument.
Expand Down
6 changes: 3 additions & 3 deletions actix-web/tests/test_server.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#[cfg(feature = "openssl")]
extern crate tls_openssl as openssl;
#[cfg(feature = "rustls-0_22")]
#[cfg(feature = "rustls-0_23")]
extern crate tls_rustls as rustls;

use std::{
Expand Down Expand Up @@ -704,7 +704,7 @@ async fn test_brotli_encoding_large_openssl() {
srv.stop().await;
}

#[cfg(feature = "rustls-0_22")]
#[cfg(feature = "rustls-0_23")]
mod plus_rustls {
use std::io::BufReader;

Expand Down Expand Up @@ -740,7 +740,7 @@ mod plus_rustls {
.map(char::from)
.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 {
// echo decompressed request body back in response
HttpResponse::Ok()
Expand Down

0 comments on commit 4fbb1ce

Please sign in to comment.