From 2d035c066ea60e9113ce9a710728a59ad03a0066 Mon Sep 17 00:00:00 2001 From: asonix Date: Sat, 18 May 2024 13:22:53 -0500 Subject: [PATCH 01/13] actix-http: Add rustls 0.23 (#3361) Co-authored-by: Rob Ede --- .github/workflows/ci-post-merge.yml | 4 ++ .github/workflows/ci.yml | 4 ++ actix-http/CHANGES.md | 5 ++ actix-http/Cargo.toml | 12 ++-- actix-http/examples/tls_rustls.rs | 5 +- actix-http/examples/ws.rs | 4 +- actix-http/src/h1/service.rs | 61 ++++++++++++++++++ actix-http/src/h2/service.rs | 51 +++++++++++++++ actix-http/src/lib.rs | 8 ++- actix-http/src/service.rs | 98 +++++++++++++++++++++++++++++ actix-http/tests/test_rustls.rs | 44 ++++++------- 11 files changed, 263 insertions(+), 33 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index 40829d8e..8d509d69 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -30,6 +30,10 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Install nasm + if: matrix.target.os == 'windows-latest' + uses: ilammy/setup-nasm@v1.5.1 + - name: Install OpenSSL if: matrix.target.os == 'windows-latest' shell: bash diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c1d959fb..56333e18 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,6 +41,10 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Install nasm + if: matrix.target.os == 'windows-latest' + uses: ilammy/setup-nasm@v1.5.1 + - name: Install OpenSSL if: matrix.target.os == 'windows-latest' shell: bash diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index 69957506..f7b20dd6 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -2,6 +2,11 @@ ## Unreleased +### Added + +- Add `rustls-0_23` crate feature +- Add `{h1::H1Service, h2::H2Service, HttpService}::rustls_0_23()` and `HttpService::rustls_0_23_with_config()` service constructors. + ### Changed - Update `brotli` dependency to `6`. diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index 05de2cb8..efd20905 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -28,6 +28,7 @@ features = [ "rustls-0_20", "rustls-0_21", "rustls-0_22", + "rustls-0_23", "compress-brotli", "compress-gzip", "compress-zstd", @@ -66,6 +67,9 @@ rustls-0_21 = ["actix-tls/accept", "actix-tls/rustls-0_21"] # TLS via Rustls v0.22 rustls-0_22 = ["actix-tls/accept", "actix-tls/rustls-0_22"] +# TLS via Rustls v0.23 +rustls-0_23 = ["actix-tls/accept", "actix-tls/rustls-0_23"] + # Compression codecs compress-brotli = ["__compress", "brotli"] compress-gzip = ["__compress", "flate2"] @@ -121,7 +125,7 @@ zstd = { version = "0.13", optional = true } [dev-dependencies] actix-http-test = { version = "3", features = ["openssl"] } actix-server = "2" -actix-tls = { version = "3.3", features = ["openssl", "rustls-0_22-webpki-roots"] } +actix-tls = { version = "3.4", features = ["openssl", "rustls-0_23-webpki-roots"] } actix-web = "4" async-stream = "0.3" @@ -139,16 +143,16 @@ serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" static_assertions = "1" tls-openssl = { package = "openssl", version = "0.10.55" } -tls-rustls_022 = { package = "rustls", version = "0.22" } +tls-rustls_023 = { package = "rustls", version = "0.23" } tokio = { version = "1.24.2", features = ["net", "rt", "macros"] } [[example]] name = "ws" -required-features = ["ws", "rustls-0_22"] +required-features = ["ws", "rustls-0_23"] [[example]] name = "tls_rustls" -required-features = ["http2", "rustls-0_22"] +required-features = ["http2", "rustls-0_23"] [[bench]] name = "response-body-compression" diff --git a/actix-http/examples/tls_rustls.rs b/actix-http/examples/tls_rustls.rs index 47ff061c..ebb7b8b3 100644 --- a/actix-http/examples/tls_rustls.rs +++ b/actix-http/examples/tls_rustls.rs @@ -12,12 +12,11 @@ //! Protocol: HTTP/1.1 //! ``` -extern crate tls_rustls_022 as rustls; - use std::io; use actix_http::{Error, HttpService, Request, Response}; use actix_utils::future::ok; +use tls_rustls_023 as rustls; #[actix_rt::main] async fn main() -> io::Result<()> { @@ -36,7 +35,7 @@ async fn main() -> io::Result<()> { ); ok::<_, Error>(Response::ok().set_body(body)) }) - .rustls_0_22(rustls_config()) + .rustls_0_23(rustls_config()) })? .run() .await diff --git a/actix-http/examples/ws.rs b/actix-http/examples/ws.rs index 55085fd7..fac6b136 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_022 as rustls; +extern crate tls_rustls_023 as rustls; use std::{ io, @@ -30,7 +30,7 @@ async fn main() -> io::Result<()> { .bind("tls", ("127.0.0.1", 8443), || { HttpService::build() .finish(handler) - .rustls_0_22(tls_config()) + .rustls_0_23(tls_config()) })? .run() .await diff --git a/actix-http/src/h1/service.rs b/actix-http/src/h1/service.rs index 64eb39c8..f2f8a0e4 100644 --- a/actix-http/src/h1/service.rs +++ b/actix-http/src/h1/service.rs @@ -335,6 +335,67 @@ mod rustls_0_22 { } } +#[cfg(feature = "rustls-0_23")] +mod rustls_0_23 { + use std::io; + + use actix_service::ServiceFactoryExt as _; + use actix_tls::accept::{ + rustls_0_23::{reexports::ServerConfig, Acceptor, TlsStream}, + TlsError, + }; + + use super::*; + + impl H1Service, S, B, X, U> + where + S: ServiceFactory, + S::Future: 'static, + S::Error: Into>, + S::InitError: fmt::Debug, + S::Response: Into>, + + B: MessageBody, + + X: ServiceFactory, + X::Future: 'static, + X::Error: Into>, + X::InitError: fmt::Debug, + + U: ServiceFactory< + (Request, Framed, Codec>), + Config = (), + Response = (), + >, + U::Future: 'static, + U::Error: fmt::Display + Into>, + U::InitError: fmt::Debug, + { + /// Create Rustls v0.23 based service. + pub fn rustls_0_23( + self, + config: ServerConfig, + ) -> impl ServiceFactory< + TcpStream, + Config = (), + Response = (), + Error = TlsError, + 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| { + let peer_addr = io.get_ref().0.peer_addr().ok(); + (io, peer_addr) + }) + .and_then(self.map_err(TlsError::Service)) + } + } +} + impl H1Service where S: ServiceFactory, diff --git a/actix-http/src/h2/service.rs b/actix-http/src/h2/service.rs index d50ffc4e..636ac316 100644 --- a/actix-http/src/h2/service.rs +++ b/actix-http/src/h2/service.rs @@ -293,6 +293,57 @@ mod rustls_0_22 { } } +#[cfg(feature = "rustls-0_23")] +mod rustls_0_23 { + use std::io; + + use actix_service::ServiceFactoryExt as _; + use actix_tls::accept::{ + rustls_0_23::{reexports::ServerConfig, Acceptor, TlsStream}, + TlsError, + }; + + use super::*; + + impl H2Service, S, B> + where + S: ServiceFactory, + S::Future: 'static, + S::Error: Into> + 'static, + S::Response: Into> + 'static, + >::Future: 'static, + + B: MessageBody + 'static, + { + /// Create Rustls v0.23 based service. + pub fn rustls_0_23( + self, + mut config: ServerConfig, + ) -> impl ServiceFactory< + TcpStream, + Config = (), + Response = (), + Error = TlsError, + 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| { + let peer_addr = io.get_ref().0.peer_addr().ok(); + (io, peer_addr) + }) + .and_then(self.map_err(TlsError::Service)) + } + } +} + impl ServiceFactory<(T, Option)> for H2Service where T: AsyncRead + AsyncWrite + Unpin + 'static, diff --git a/actix-http/src/lib.rs b/actix-http/src/lib.rs index cb82ced0..f9697c4d 100644 --- a/actix-http/src/lib.rs +++ b/actix-http/src/lib.rs @@ -6,7 +6,10 @@ //! | ------------------- | ------------------------------------------- | //! | `http2` | HTTP/2 support via [h2]. | //! | `openssl` | TLS support via [OpenSSL]. | -//! | `rustls` | TLS support via [rustls]. | +//! | `rustls` | TLS support via [rustls] 0.20. | +//! | `rustls-0_21` | TLS support via [rustls] 0.21. | +//! | `rustls-0_22` | TLS support via [rustls] 0.22. | +//! | `rustls-0_23` | TLS support via [rustls] 0.23. | //! | `compress-brotli` | Payload compression support: Brotli. | //! | `compress-gzip` | Payload compression support: Deflate, Gzip. | //! | `compress-zstd` | Payload compression support: Zstd. | @@ -28,7 +31,7 @@ #![doc(html_favicon_url = "https://actix.rs/favicon.ico")] #![cfg_attr(docsrs, feature(doc_auto_cfg))] -pub use ::http::{uri, uri::Uri, Method, StatusCode, Version}; +pub use http::{uri, uri::Uri, Method, StatusCode, Version}; pub mod body; mod builder; @@ -63,6 +66,7 @@ pub use self::payload::PayloadStream; feature = "rustls-0_20", feature = "rustls-0_21", feature = "rustls-0_22", + feature = "rustls-0_23", ))] pub use self::service::TlsAcceptorConfig; pub use self::{ diff --git a/actix-http/src/service.rs b/actix-http/src/service.rs index e2438718..a58be93c 100644 --- a/actix-http/src/service.rs +++ b/actix-http/src/service.rs @@ -246,6 +246,7 @@ where feature = "rustls-0_20", feature = "rustls-0_21", feature = "rustls-0_22", + feature = "rustls-0_23", ))] #[derive(Debug, Default)] pub struct TlsAcceptorConfig { @@ -257,6 +258,7 @@ pub struct TlsAcceptorConfig { feature = "rustls-0_20", feature = "rustls-0_21", feature = "rustls-0_22", + feature = "rustls-0_23", ))] impl TlsAcceptorConfig { /// Set TLS handshake timeout duration. @@ -650,6 +652,102 @@ mod rustls_0_22 { } } +#[cfg(feature = "rustls-0_23")] +mod rustls_0_23 { + use std::io; + + use actix_service::ServiceFactoryExt as _; + use actix_tls::accept::{ + rustls_0_23::{reexports::ServerConfig, Acceptor, TlsStream}, + TlsError, + }; + + use super::*; + + impl HttpService, S, B, X, U> + where + S: ServiceFactory, + S::Future: 'static, + S::Error: Into> + 'static, + S::InitError: fmt::Debug, + S::Response: Into> + 'static, + >::Future: 'static, + + B: MessageBody + 'static, + + X: ServiceFactory, + X::Future: 'static, + X::Error: Into>, + X::InitError: fmt::Debug, + + U: ServiceFactory< + (Request, Framed, h1::Codec>), + Config = (), + Response = (), + >, + U::Future: 'static, + U::Error: fmt::Display + Into>, + U::InitError: fmt::Debug, + { + /// Create Rustls v0.23 based service. + pub fn rustls_0_23( + self, + config: ServerConfig, + ) -> impl ServiceFactory< + TcpStream, + Config = (), + Response = (), + Error = TlsError, + InitError = (), + > { + self.rustls_0_23_with_config(config, TlsAcceptorConfig::default()) + } + + /// Create Rustls v0.23 based service with custom TLS acceptor configuration. + pub fn rustls_0_23_with_config( + self, + mut config: ServerConfig, + tls_acceptor_config: TlsAcceptorConfig, + ) -> impl ServiceFactory< + TcpStream, + Config = (), + Response = (), + Error = TlsError, + 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| 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 ServiceFactory<(T, Protocol, Option)> for HttpService where diff --git a/actix-http/tests/test_rustls.rs b/actix-http/tests/test_rustls.rs index 08b3a249..fd2064d5 100644 --- a/actix-http/tests/test_rustls.rs +++ b/actix-http/tests/test_rustls.rs @@ -1,6 +1,6 @@ -#![cfg(feature = "rustls-0_22")] +#![cfg(feature = "rustls-0_23")] -extern crate tls_rustls_022 as rustls; +extern crate tls_rustls_023 as rustls; use std::{ convert::Infallible, @@ -20,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_0_22::webpki_roots_cert_store; +use actix_tls::connect::rustls_0_23::webpki_roots_cert_store; use actix_utils::future::{err, ok, poll_fn}; use bytes::{Bytes, BytesMut}; use derive_more::{Display, Error}; @@ -108,7 +108,7 @@ async fn h1() -> io::Result<()> { let srv = test_server(move || { HttpService::build() .h1(|_| ok::<_, Error>(Response::ok())) - .rustls_0_22(tls_config()) + .rustls_0_23(tls_config()) }) .await; @@ -122,7 +122,7 @@ async fn h2() -> io::Result<()> { let srv = test_server(move || { HttpService::build() .h2(|_| ok::<_, Error>(Response::ok())) - .rustls_0_22(tls_config()) + .rustls_0_23(tls_config()) }) .await; @@ -140,7 +140,7 @@ async fn h1_1() -> io::Result<()> { assert_eq!(req.version(), Version::HTTP_11); ok::<_, Error>(Response::ok()) }) - .rustls_0_22(tls_config()) + .rustls_0_23(tls_config()) }) .await; @@ -158,7 +158,7 @@ async fn h2_1() -> io::Result<()> { assert_eq!(req.version(), Version::HTTP_2); ok::<_, Error>(Response::ok()) }) - .rustls_0_22_with_config( + .rustls_0_23_with_config( tls_config(), TlsAcceptorConfig::default().handshake_timeout(Duration::from_secs(5)), ) @@ -179,7 +179,7 @@ async fn h2_body1() -> io::Result<()> { let body = load_body(req.take_payload()).await?; Ok::<_, Error>(Response::ok().set_body(body)) }) - .rustls_0_22(tls_config()) + .rustls_0_23(tls_config()) }) .await; @@ -205,7 +205,7 @@ async fn h2_content_length() { ]; ok::<_, Infallible>(Response::new(statuses[indx])) }) - .rustls_0_22(tls_config()) + .rustls_0_23(tls_config()) }) .await; @@ -277,7 +277,7 @@ async fn h2_headers() { } ok::<_, Infallible>(config.body(data.clone())) }) - .rustls_0_22(tls_config()) + .rustls_0_23(tls_config()) }) .await; @@ -316,7 +316,7 @@ async fn h2_body2() { let mut srv = test_server(move || { HttpService::build() .h2(|_| ok::<_, Infallible>(Response::ok().set_body(STR))) - .rustls_0_22(tls_config()) + .rustls_0_23(tls_config()) }) .await; @@ -333,7 +333,7 @@ async fn h2_head_empty() { let mut srv = test_server(move || { HttpService::build() .finish(|_| ok::<_, Infallible>(Response::ok().set_body(STR))) - .rustls_0_22(tls_config()) + .rustls_0_23(tls_config()) }) .await; @@ -359,7 +359,7 @@ async fn h2_head_binary() { let mut srv = test_server(move || { HttpService::build() .h2(|_| ok::<_, Infallible>(Response::ok().set_body(STR))) - .rustls_0_22(tls_config()) + .rustls_0_23(tls_config()) }) .await; @@ -384,7 +384,7 @@ async fn h2_head_binary2() { let srv = test_server(move || { HttpService::build() .h2(|_| ok::<_, Infallible>(Response::ok().set_body(STR))) - .rustls_0_22(tls_config()) + .rustls_0_23(tls_config()) }) .await; @@ -410,7 +410,7 @@ async fn h2_body_length() { Response::ok().set_body(SizedStream::new(STR.len() as u64, body)), ) }) - .rustls_0_22(tls_config()) + .rustls_0_23(tls_config()) }) .await; @@ -434,7 +434,7 @@ async fn h2_body_chunked_explicit() { .body(BodyStream::new(body)), ) }) - .rustls_0_22(tls_config()) + .rustls_0_23(tls_config()) }) .await; @@ -463,7 +463,7 @@ async fn h2_response_http_error_handling() { ) })) })) - .rustls_0_22(tls_config()) + .rustls_0_23(tls_config()) }) .await; @@ -493,7 +493,7 @@ async fn h2_service_error() { let mut srv = test_server(move || { HttpService::build() .h2(|_| err::, _>(BadRequest)) - .rustls_0_22(tls_config()) + .rustls_0_23(tls_config()) }) .await; @@ -510,7 +510,7 @@ async fn h1_service_error() { let mut srv = test_server(move || { HttpService::build() .h1(|_| err::, _>(BadRequest)) - .rustls_0_22(tls_config()) + .rustls_0_23(tls_config()) }) .await; @@ -533,7 +533,7 @@ async fn alpn_h1() -> io::Result<()> { config.alpn_protocols.push(CUSTOM_ALPN_PROTOCOL.to_vec()); HttpService::build() .h1(|_| ok::<_, Error>(Response::ok())) - .rustls_0_22(config) + .rustls_0_23(config) }) .await; @@ -555,7 +555,7 @@ async fn alpn_h2() -> io::Result<()> { config.alpn_protocols.push(CUSTOM_ALPN_PROTOCOL.to_vec()); HttpService::build() .h2(|_| ok::<_, Error>(Response::ok())) - .rustls_0_22(config) + .rustls_0_23(config) }) .await; @@ -581,7 +581,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_0_22(config) + .rustls_0_23(config) }) .await; From 0a2788d6627ed26d3fec560474b1c7f9febd78db Mon Sep 17 00:00:00 2001 From: Matt Palmer Date: Sun, 19 May 2024 04:57:35 +1000 Subject: [PATCH 02/13] actix-test: re-export types from awc (#3349) This allows us to pass these types around in functions, without having to add `awc` as a direct (dev-)dependency. Co-authored-by: Rob Ede --- actix-test/CHANGES.md | 1 + actix-test/src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/actix-test/CHANGES.md b/actix-test/CHANGES.md index 08252044..f465720f 100644 --- a/actix-test/CHANGES.md +++ b/actix-test/CHANGES.md @@ -3,6 +3,7 @@ ## Unreleased - Minimum supported Rust version (MSRV) is now 1.72. +- Various types from `awc`, such as `ClientRequest` and `ClientResponse`, are now re-exported. ## 0.1.3 diff --git a/actix-test/src/lib.rs b/actix-test/src/lib.rs index b7aeddad..b90db638 100644 --- a/actix-test/src/lib.rs +++ b/actix-test/src/lib.rs @@ -52,7 +52,7 @@ use actix_web::{ rt::{self, System}, web, Error, }; -use awc::{error::PayloadError, Client, ClientRequest, ClientResponse, Connector}; +pub use awc::{error::PayloadError, Client, ClientRequest, ClientResponse, Connector}; use futures_core::Stream; use tokio::sync::mpsc; From 48d7adb7bfee8e373e31e9fe6c78a7da4cec5bec Mon Sep 17 00:00:00 2001 From: Raphael C Date: Sat, 18 May 2024 21:02:00 +0200 Subject: [PATCH 03/13] Documentation for actix multipart (#3344) example for actix-multipart readme & crate docs Co-authored-by: Rob Ede --- actix-multipart/README.md | 62 ++++++++++++++++++++++++++++++++++++++ actix-multipart/src/lib.rs | 35 +++++++++++++++++++++ 2 files changed, 97 insertions(+) diff --git a/actix-multipart/README.md b/actix-multipart/README.md index 56723bd6..83947b0c 100644 --- a/actix-multipart/README.md +++ b/actix-multipart/README.md @@ -14,3 +14,65 @@ [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) + + +## Example + +Dependencies: + +```toml +[dependencies] +actix-multipart = "0.6" +actix-web = "4.5" +serde = { version = "1.0", features = ["derive"] } +``` + +Code: + +```rust +use actix_web::{post, App, HttpServer, Responder}; + +use actix_multipart::form::{json::Json as MPJson, tempfile::TempFile, MultipartForm}; +use serde::Deserialize; + +#[derive(Debug, Deserialize)] +struct Metadata { + name: String, +} + +#[derive(Debug, MultipartForm)] +struct UploadForm { + #[multipart(limit = "100MB")] + file: TempFile, + json: MPJson, +} + +#[post("/videos")] +pub async fn post_video(MultipartForm(form): MultipartForm) -> impl Responder { + format!( + "Uploaded file {}, with size: {}", + form.json.name, form.file.size + ) +} + +#[actix_web::main] +async fn main() -> std::io::Result<()> { + HttpServer::new(move || App::new().service(post_video)) + .bind(("127.0.0.1", 8080))? + .run() + .await +} +``` + +Curl request : +```bash +curl -v --request POST \ + --url http://localhost:8080/videos \ + -F 'json={"name": "Cargo.lock"};type=application/json' \ + -F file=@./Cargo.lock +``` + + +### Examples + +https://github.com/actix/examples/tree/master/forms/multipart \ No newline at end of file diff --git a/actix-multipart/src/lib.rs b/actix-multipart/src/lib.rs index c06a00ca..d19e951e 100644 --- a/actix-multipart/src/lib.rs +++ b/actix-multipart/src/lib.rs @@ -1,4 +1,39 @@ //! Multipart form support for Actix Web. +//! # Examples +//! ```no_run +//! use actix_web::{post, App, HttpServer, Responder}; +//! +//! use actix_multipart::form::{json::Json as MPJson, tempfile::TempFile, MultipartForm}; +//! use serde::Deserialize; +//! +//! #[derive(Debug, Deserialize)] +//! struct Metadata { +//! name: String, +//! } +//! +//! #[derive(Debug, MultipartForm)] +//! struct UploadForm { +//! #[multipart(limit = "100MB")] +//! file: TempFile, +//! json: MPJson, +//! } +//! +//! #[post("/videos")] +//! pub async fn post_video(MultipartForm(form): MultipartForm) -> impl Responder { +//! format!( +//! "Uploaded file {}, with size: {}", +//! form.json.name, form.file.size +//! ) +//! } +//! +//! #[actix_web::main] +//! async fn main() -> std::io::Result<()> { +//! HttpServer::new(move || App::new().service(post_video)) +//! .bind(("127.0.0.1", 8080))? +//! .run() +//! .await +//! } +//! ``` #![deny(rust_2018_idioms, nonstandard_style)] #![warn(future_incompatible)] From 2e63ff5928abc0704cadf330bcbf630162a37fa8 Mon Sep 17 00:00:00 2001 From: asonix Date: Sat, 18 May 2024 14:05:58 -0500 Subject: [PATCH 04/13] actix-web: Add rustls 0.23 (#3363) * Fix type confusion in some scenarios When the feature for rustls 0.22 is enabled, and rustls 0.23 is also present in a project, there suddently exist multiple paths for errors when building middleware chains due to the use of two consecutive `?` operators without specifying the intermediate error type. This commit addresses the issue by removing the first `?`, so that the first error type will always be known, and the second `?` always has a well defined implementation. * Add CHANGES entry about type confusion * actix-http: add rustls 0.23 support * actix-http: update ws example, tests for rustls 0.23 * actix-http: add rustls 0.23 to changelog * Update comments to mention 0.23 instead of 0.22 * awc: add rustls 0.23 support This also fixes certificate lookup when native-roots is enabled for rustls 0.22. * awc: update changelog for rustls 0.23 * awc: Add base rustls-0_23 feature without roots to better enable custom config * actix-test: add rustls-0.23 * actix-test: add rustls 0.23 to changelog * awc: update changelog with rustls 0.23 tweaks * actix-web: add rustls 0.23 * Add rustls-0_23 to CI * Update tls_rustls.rs * review nits * review nits part 2 * fix doc test --------- Co-authored-by: Rob Ede --- actix-http/examples/tls_rustls.rs | 3 +- actix-test/CHANGES.md | 1 + actix-test/Cargo.toml | 3 + actix-test/src/lib.rs | 53 ++++++++++++++++ actix-web/CHANGES.md | 3 + actix-web/Cargo.toml | 7 +- actix-web/src/lib.rs | 5 +- actix-web/src/server.rs | 102 +++++++++++++++++++++++++++++- actix-web/tests/test_server.rs | 6 +- awc/CHANGES.md | 3 + awc/Cargo.toml | 15 ++++- awc/src/builder.rs | 6 ++ awc/src/client/connector.rs | 97 ++++++++++++++++++++++++++-- awc/tests/test_rustls_client.rs | 12 ++-- 14 files changed, 292 insertions(+), 24 deletions(-) diff --git a/actix-http/examples/tls_rustls.rs b/actix-http/examples/tls_rustls.rs index ebb7b8b3..3e273d79 100644 --- a/actix-http/examples/tls_rustls.rs +++ b/actix-http/examples/tls_rustls.rs @@ -12,11 +12,12 @@ //! Protocol: HTTP/1.1 //! ``` +extern crate tls_rustls_023 as rustls; + use std::io; use actix_http::{Error, HttpService, Request, Response}; use actix_utils::future::ok; -use tls_rustls_023 as rustls; #[actix_rt::main] async fn main() -> io::Result<()> { diff --git a/actix-test/CHANGES.md b/actix-test/CHANGES.md index f465720f..b55a8305 100644 --- a/actix-test/CHANGES.md +++ b/actix-test/CHANGES.md @@ -2,6 +2,7 @@ ## Unreleased +- Add `TestServerConfig::rustls_0_23()` method for Rustls v0.23 support behind new `rustls-0_23` crate feature. - Minimum supported Rust version (MSRV) is now 1.72. - Various types from `awc`, such as `ClientRequest` and `ClientResponse`, are now re-exported. diff --git a/actix-test/Cargo.toml b/actix-test/Cargo.toml index 7f48fc2c..69ce080a 100644 --- a/actix-test/Cargo.toml +++ b/actix-test/Cargo.toml @@ -29,6 +29,8 @@ rustls-0_20 = ["tls-rustls-0_20", "actix-http/rustls-0_20", "awc/rustls-0_20"] rustls-0_21 = ["tls-rustls-0_21", "actix-http/rustls-0_21", "awc/rustls-0_21"] # TLS via Rustls v0.22 rustls-0_22 = ["tls-rustls-0_22", "actix-http/rustls-0_22", "awc/rustls-0_22-webpki-roots"] +# TLS via Rustls v0.23 +rustls-0_23 = ["tls-rustls-0_23", "actix-http/rustls-0_23", "awc/rustls-0_23-webpki-roots"] # TLS via OpenSSL openssl = ["tls-openssl", "actix-http/openssl", "awc/openssl"] @@ -53,4 +55,5 @@ tls-openssl = { package = "openssl", version = "0.10.55", optional = true } tls-rustls-0_20 = { package = "rustls", version = "0.20", optional = true } tls-rustls-0_21 = { package = "rustls", version = "0.21", optional = true } tls-rustls-0_22 = { package = "rustls", version = "0.22", optional = true } +tls-rustls-0_23 = { package = "rustls", version = "0.23", default-features = false, optional = true } tokio = { version = "1.24.2", features = ["sync"] } diff --git a/actix-test/src/lib.rs b/actix-test/src/lib.rs index b90db638..1c3d8ff1 100644 --- a/actix-test/src/lib.rs +++ b/actix-test/src/lib.rs @@ -145,6 +145,8 @@ where StreamType::Rustls021(_) => true, #[cfg(feature = "rustls-0_22")] StreamType::Rustls022(_) => true, + #[cfg(feature = "rustls-0_23")] + StreamType::Rustls023(_) => true, }; // run server in separate orphaned thread @@ -371,6 +373,48 @@ where .rustls_0_22(config.clone()) }), }, + #[cfg(feature = "rustls-0_23")] + StreamType::Rustls023(config) => match cfg.tp { + HttpVer::Http1 => builder.listen("test", tcp, move || { + let app_cfg = + AppConfig::__priv_test_new(false, local_addr.to_string(), local_addr); + + let fac = factory() + .into_factory() + .map_err(|err| err.into().error_response()); + + HttpService::build() + .client_request_timeout(timeout) + .h1(map_config(fac, move |_| app_cfg.clone())) + .rustls_0_23(config.clone()) + }), + HttpVer::Http2 => builder.listen("test", tcp, move || { + let app_cfg = + AppConfig::__priv_test_new(false, local_addr.to_string(), local_addr); + + let fac = factory() + .into_factory() + .map_err(|err| err.into().error_response()); + + HttpService::build() + .client_request_timeout(timeout) + .h2(map_config(fac, move |_| app_cfg.clone())) + .rustls_0_23(config.clone()) + }), + HttpVer::Both => builder.listen("test", tcp, move || { + let app_cfg = + AppConfig::__priv_test_new(false, local_addr.to_string(), local_addr); + + let fac = factory() + .into_factory() + .map_err(|err| err.into().error_response()); + + HttpService::build() + .client_request_timeout(timeout) + .finish(map_config(fac, move |_| app_cfg.clone())) + .rustls_0_23(config.clone()) + }), + }, } .expect("test server could not be created"); @@ -447,6 +491,8 @@ enum StreamType { Rustls021(tls_rustls_0_21::ServerConfig), #[cfg(feature = "rustls-0_22")] Rustls022(tls_rustls_0_22::ServerConfig), + #[cfg(feature = "rustls-0_23")] + Rustls023(tls_rustls_0_23::ServerConfig), } /// Create default test server config. @@ -537,6 +583,13 @@ impl TestServerConfig { self } + /// Accepts secure connections via Rustls v0.23. + #[cfg(feature = "rustls-0_23")] + pub fn rustls_0_23(mut self, config: tls_rustls_0_23::ServerConfig) -> Self { + self.stream = StreamType::Rustls023(config); + self + } + /// Sets client timeout for first request. pub fn client_request_timeout(mut self, dur: Duration) -> Self { self.client_request_timeout = dur; diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index ea996769..5b43a51d 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -5,6 +5,9 @@ ### 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 diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index b4c71381..cd09c305 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -27,6 +27,7 @@ features = [ "rustls-0_20", "rustls-0_21", "rustls-0_22", + "rustls-0_23", "compress-brotli", "compress-gzip", "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"] # 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"] @@ -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 = "6" @@ -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" diff --git a/actix-web/src/lib.rs b/actix-web/src/lib.rs index 88f0ae9b..f86a7440 100644 --- a/actix-web/src/lib.rs +++ b/actix-web/src/lib.rs @@ -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)] diff --git a/actix-web/src/server.rs b/actix-web/src/server.rs index 6592079b..33b1e189 100644 --- a/actix-web/src/server.rs +++ b/actix-web/src/server.rs @@ -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}; @@ -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() @@ -270,6 +277,10 @@ where /// Rustls v0.20. /// - `actix_tls::accept::rustls_0_21::TlsStream` when using /// Rustls v0.21. + /// - `actix_tls::accept::rustls_0_22::TlsStream` when using + /// Rustls v0.22. + /// - `actix_tls::accept::rustls_0_23::TlsStream` when using + /// Rustls v0.23. /// - `actix_web::rt::net::TcpStream` when no encryption is used. /// /// See the `on_connect` example for additional details. @@ -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( + mut self, + addrs: A, + config: actix_tls::accept::rustls_0_23::reexports::ServerConfig, + ) -> io::Result { + 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. /// @@ -595,7 +625,7 @@ where /// Binds to existing listener for accepting incoming TLS connection requests using Rustls /// v0.21. /// - /// See [`listen()`](Self::listen) for more details on the `lst` argument. + /// 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_21")] @@ -712,7 +742,7 @@ where /// Binds to existing listener for accepting incoming TLS connection requests using Rustls /// v0.22. /// - /// See [`listen()`](Self::listen) for more details on the `lst` argument. + /// 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_22")] @@ -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.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 { + 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. diff --git a/actix-web/tests/test_server.rs b/actix-web/tests/test_server.rs index 8fb80216..60d28235 100644 --- a/actix-web/tests/test_server.rs +++ b/actix-web/tests/test_server.rs @@ -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::{ @@ -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; @@ -740,7 +740,7 @@ mod plus_rustls { .map(char::from) .collect::(); - 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() diff --git a/awc/CHANGES.md b/awc/CHANGES.md index 9bb787ab..4031d2bd 100644 --- a/awc/CHANGES.md +++ b/awc/CHANGES.md @@ -2,6 +2,9 @@ ## Unreleased +- Add `rustls-0_23`, `rustls-0_23-webpki-roots`, and `rustls-0_23-native-roots` crate features. +- Add `awc::Connector::rustls_0_23()` constructor. +- Fix `rustls-0_22-native-roots` root store lookup - Update `brotli` dependency to `6`. - Minimum supported Rust version (MSRV) is now 1.72. diff --git a/awc/Cargo.toml b/awc/Cargo.toml index aa77b024..2ba8ada3 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -27,6 +27,7 @@ features = [ "rustls-0_20", "rustls-0_21", "rustls-0_22-webpki-roots", + "rustls-0_23-webpki-roots", "compress-brotli", "compress-gzip", "compress-zstd", @@ -48,6 +49,12 @@ rustls-0_21 = ["tls-rustls-0_21", "actix-tls/rustls-0_21"] rustls-0_22-webpki-roots = ["tls-rustls-0_22", "actix-tls/rustls-0_22-webpki-roots"] # TLS via Rustls v0.22 (Native roots) rustls-0_22-native-roots = ["tls-rustls-0_22", "actix-tls/rustls-0_22-native-roots"] +# TLS via Rustls v0.23 +rustls-0_23 = ["tls-rustls-0_23", "actix-tls/rustls-0_23"] +# TLS via Rustls v0.23 (WebPKI roots) +rustls-0_23-webpki-roots = ["rustls-0_23", "actix-tls/rustls-0_23-webpki-roots"] +# TLS via Rustls v0.23 (Native roots) +rustls-0_23-native-roots = ["rustls-0_23", "actix-tls/rustls-0_23-native-roots"] # Brotli algorithm content-encoding support compress-brotli = ["actix-http/compress-brotli", "__compress"] @@ -104,6 +111,7 @@ tls-openssl = { package = "openssl", version = "0.10.55", optional = true } tls-rustls-0_20 = { package = "rustls", version = "0.20", optional = true, features = ["dangerous_configuration"] } tls-rustls-0_21 = { package = "rustls", version = "0.21", optional = true, features = ["dangerous_configuration"] } tls-rustls-0_22 = { package = "rustls", version = "0.22", optional = true } +tls-rustls-0_23 = { package = "rustls", version = "0.23", optional = true, default-features = false } trust-dns-resolver = { version = "0.23", optional = true } @@ -111,8 +119,8 @@ trust-dns-resolver = { version = "0.23", optional = true } actix-http = { version = "3.6", features = ["openssl"] } actix-http-test = { version = "3", features = ["openssl"] } actix-server = "2" -actix-test = { version = "0.1", features = ["openssl", "rustls-0_22"] } -actix-tls = { version = "3.3", features = ["openssl", "rustls-0_22"] } +actix-test = { version = "0.1", features = ["openssl", "rustls-0_23"] } +actix-tls = { version = "3.3", features = ["openssl", "rustls-0_23"] } actix-utils = "3" actix-web = { version = "4", features = ["openssl"] } @@ -126,7 +134,8 @@ rcgen = "0.12" rustls-pemfile = "2" tokio = { version = "1.24.2", features = ["rt-multi-thread", "macros"] } zstd = "0.13" +tls-rustls-0_23 = { package = "rustls", version = "0.23" } # add rustls 0.23 with default features to make aws_lc_rs work in tests [[example]] name = "client" -required-features = ["rustls-0_22-webpki-roots"] +required-features = ["rustls-0_23-webpki-roots"] diff --git a/awc/src/builder.rs b/awc/src/builder.rs index a5496038..5aae394f 100644 --- a/awc/src/builder.rs +++ b/awc/src/builder.rs @@ -37,6 +37,12 @@ pub struct ClientBuilder { } impl ClientBuilder { + /// Create a new ClientBuilder with default settings + /// + /// Note: If the `rustls-0_23` feature is enabled and neither `rustls-0_23-native-roots` nor + /// `rustls-0_23-webpki-roots` are enabled, this ClientBuilder will build without TLS. In order + /// to enable TLS in this scenario, a custom `Connector` _must_ be added to the builder before + /// finishing construction. #[allow(clippy::new_ret_no_self)] pub fn new() -> ClientBuilder< impl Service< diff --git a/awc/src/client/connector.rs b/awc/src/client/connector.rs index b66e13ec..fbe50b65 100644 --- a/awc/src/client/connector.rs +++ b/awc/src/client/connector.rs @@ -57,6 +57,10 @@ enum OurTlsConnector { ))] #[allow(dead_code)] // false positive; used in build_tls Rustls022(std::sync::Arc), + + #[cfg(feature = "rustls-0_23")] + #[allow(dead_code)] // false positive; used in build_tls + Rustls023(std::sync::Arc), } /// Manages HTTP client network connectivity. @@ -80,6 +84,14 @@ pub struct Connector { } impl Connector<()> { + /// Create a new connector with default TLS settings + /// + /// # Panics + /// + /// - When the `rustls-0_23-webpki-roots` or `rustls-0_23-native-roots` features are enabled + /// and no default crypto provider has been loaded, this method will panic. + /// - When the `rustls-0_23-native-roots` or `rustls-0_22-native-roots` features are enabled + /// and the runtime system has no native root certificates, this method will panic. #[allow(clippy::new_ret_no_self, clippy::let_unit_value)] pub fn new() -> Connector< impl Service< @@ -96,10 +108,32 @@ impl Connector<()> { } cfg_if::cfg_if! { - if #[cfg(any(feature = "rustls-0_22-webpki-roots", feature = "rustls-0_22-webpki-roots"))] { - /// Build TLS connector with Rustls v0.22, based on supplied ALPN protocols. + if #[cfg(any(feature = "rustls-0_23-webpki-roots", feature = "rustls-0_23-native-roots"))] { + /// Build TLS connector with Rustls v0.23, based on supplied ALPN protocols. /// - /// Note that if other TLS crate features are enabled, Rustls v0.22 will be used. + /// Note that if other TLS crate features are enabled, Rustls v0.23 will be used. + fn build_tls(protocols: Vec>) -> OurTlsConnector { + use actix_tls::connect::rustls_0_23::{self, reexports::ClientConfig}; + + cfg_if::cfg_if! { + if #[cfg(feature = "rustls-0_23-webpki-roots")] { + let certs = rustls_0_23::webpki_roots_cert_store(); + } else if #[cfg(feature = "rustls-0_23-native-roots")] { + let certs = rustls_0_23::native_roots_cert_store().expect("Failed to find native root certificates"); + } + } + + let mut config = ClientConfig::builder() + .with_root_certificates(certs) + .with_no_client_auth(); + + config.alpn_protocols = protocols; + + OurTlsConnector::Rustls023(std::sync::Arc::new(config)) + } + + } else if #[cfg(any(feature = "rustls-0_22-webpki-roots", feature = "rustls-0_22-native-roots"))] { + /// Build TLS connector with Rustls v0.22, based on supplied ALPN protocols. fn build_tls(protocols: Vec>) -> OurTlsConnector { use actix_tls::connect::rustls_0_22::{self, reexports::ClientConfig}; @@ -107,7 +141,7 @@ impl Connector<()> { if #[cfg(feature = "rustls-0_22-webpki-roots")] { let certs = rustls_0_22::webpki_roots_cert_store(); } else if #[cfg(feature = "rustls-0_22-native-roots")] { - let certs = rustls_0_22::native_roots_cert_store(); + let certs = rustls_0_22::native_roots_cert_store().expect("Failed to find native root certificates"); } } @@ -167,7 +201,8 @@ impl Connector<()> { OurTlsConnector::OpensslBuilder(ssl) } } else { - /// Provides an empty TLS connector when no TLS feature is enabled. + /// Provides an empty TLS connector when no TLS feature is enabled, or when only the + /// `rustls-0_23` crate feature is enabled. fn build_tls(_: Vec>) -> OurTlsConnector { OurTlsConnector::None } @@ -278,6 +313,24 @@ where self } + /// Sets custom Rustls v0.23 `ClientConfig` instance. + /// + /// In order to enable ALPN, set the `.alpn_protocols` field on the ClientConfig to the + /// following: + /// + /// ```no_run + /// vec![b"h2".to_vec(), b"http/1.1".to_vec()] + /// # ; + /// ``` + #[cfg(feature = "rustls-0_23")] + pub fn rustls_0_23( + mut self, + connector: std::sync::Arc, + ) -> Self { + self.tls = OurTlsConnector::Rustls023(connector); + self + } + /// Sets maximum supported HTTP major version. /// /// Supported versions are HTTP/1.1 and HTTP/2. @@ -588,6 +641,40 @@ where Some(actix_service::boxed::rc_service(tls_service)) } + + #[cfg(feature = "rustls-0_23")] + OurTlsConnector::Rustls023(tls) => { + const H2: &[u8] = b"h2"; + + use actix_tls::connect::rustls_0_23::{reexports::AsyncTlsStream, TlsConnector}; + + #[allow(non_local_definitions)] + impl IntoConnectionIo for TcpConnection> { + fn into_connection_io(self) -> (Box, Protocol) { + let sock = self.into_parts().0; + let h2 = sock + .get_ref() + .1 + .alpn_protocol() + .map_or(false, |protos| protos.windows(2).any(|w| w == H2)); + if h2 { + (Box::new(sock), Protocol::Http2) + } else { + (Box::new(sock), Protocol::Http1) + } + } + } + + let handshake_timeout = self.config.handshake_timeout; + + let tls_service = TlsConnectorService { + tcp_service: tcp_service_inner, + tls_service: TlsConnector::service(tls), + timeout: handshake_timeout, + }; + + Some(actix_service::boxed::rc_service(tls_service)) + } }; let tcp_config = self.config.no_disconnect_timeout(); diff --git a/awc/tests/test_rustls_client.rs b/awc/tests/test_rustls_client.rs index 1cc3e8c4..719d2511 100644 --- a/awc/tests/test_rustls_client.rs +++ b/awc/tests/test_rustls_client.rs @@ -1,6 +1,6 @@ -#![cfg(feature = "rustls-0_22-webpki-roots")] +#![cfg(feature = "rustls-0_23-webpki-roots")] -extern crate tls_rustls_0_22 as rustls; +extern crate tls_rustls_0_23 as rustls; use std::{ io::BufReader, @@ -13,7 +13,7 @@ use std::{ use actix_http::HttpService; use actix_http_test::test_server; use actix_service::{fn_service, map_config, ServiceFactoryExt}; -use actix_tls::connect::rustls_0_22::webpki_roots_cert_store; +use actix_tls::connect::rustls_0_23::webpki_roots_cert_store; use actix_utils::future::ok; use actix_web::{dev::AppConfig, http::Version, web, App, HttpResponse}; use rustls::{ @@ -83,7 +83,7 @@ mod danger { } fn supported_verify_schemes(&self) -> Vec { - rustls::crypto::ring::default_provider() + rustls::crypto::aws_lc_rs::default_provider() .signature_verification_algorithms .supported_schemes() } @@ -107,7 +107,7 @@ async fn test_connection_reuse_h2() { App::new().service(web::resource("/").route(web::to(HttpResponse::Ok))), |_| AppConfig::default(), )) - .rustls_0_22(tls_config()) + .rustls_0_23(tls_config()) .map_err(|_| ()), ) }) @@ -126,7 +126,7 @@ async fn test_connection_reuse_h2() { .set_certificate_verifier(Arc::new(danger::NoCertificateVerification)); let client = awc::Client::builder() - .connector(awc::Connector::new().rustls_0_22(Arc::new(config))) + .connector(awc::Connector::new().rustls_0_23(Arc::new(config))) .finish(); // req 1 From 18e02b83d5e160d3fe7e051104eea700f8eaa3af Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sat, 18 May 2024 20:35:12 +0100 Subject: [PATCH 05/13] docs: fix middleware docs warning --- actix-web/src/middleware/mod.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/actix-web/src/middleware/mod.rs b/actix-web/src/middleware/mod.rs index ed61556a..e924de26 100644 --- a/actix-web/src/middleware/mod.rs +++ b/actix-web/src/middleware/mod.rs @@ -33,13 +33,13 @@ //! //! # fn main() { //! # // These aren't snake_case, because they are supposed to be unit structs. -//! # let MiddlewareA = middleware::Compress::default(); -//! # let MiddlewareB = middleware::Compress::default(); -//! # let MiddlewareC = middleware::Compress::default(); +//! # type MiddlewareA = middleware::Compress; +//! # type MiddlewareB = middleware::Compress; +//! # type MiddlewareC = middleware::Compress; //! let app = App::new() -//! .wrap(MiddlewareA) -//! .wrap(MiddlewareB) -//! .wrap(MiddlewareC) +//! .wrap(MiddlewareA::default()) +//! .wrap(MiddlewareB::default()) +//! .wrap(MiddlewareC::default()) //! .service(service); //! # } //! ``` From e8262da1381c24a265747ac604e45aee635e00b8 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 19 May 2024 10:12:32 +0100 Subject: [PATCH 06/13] chore: update rcgen to 0.13 --- actix-http/Cargo.toml | 2 +- actix-http/examples/tls_rustls.rs | 7 ++++--- actix-http/examples/ws.rs | 7 ++++--- actix-http/tests/test_openssl.rs | 8 +++++--- actix-http/tests/test_rustls.rs | 7 ++++--- actix-web/Cargo.toml | 2 +- actix-web/tests/test_httpserver.rs | 8 +++++--- actix-web/tests/test_server.rs | 15 +++++++++------ awc/Cargo.toml | 2 +- awc/tests/test_connector.rs | 8 +++++--- awc/tests/test_rustls_client.rs | 7 ++++--- awc/tests/test_ssl_client.rs | 8 +++++--- 12 files changed, 48 insertions(+), 33 deletions(-) diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index efd20905..c00c2ee0 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -135,7 +135,7 @@ env_logger = "0.11" futures-util = { version = "0.3.17", default-features = false, features = ["alloc"] } memchr = "2.4" once_cell = "1.9" -rcgen = "0.12" +rcgen = "0.13" regex = "1.3" rustversion = "1" rustls-pemfile = "2" diff --git a/actix-http/examples/tls_rustls.rs b/actix-http/examples/tls_rustls.rs index 3e273d79..17303c55 100644 --- a/actix-http/examples/tls_rustls.rs +++ b/actix-http/examples/tls_rustls.rs @@ -43,9 +43,10 @@ async fn main() -> io::Result<()> { } 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 rcgen::CertifiedKey { cert, key_pair } = + rcgen::generate_simple_self_signed(["localhost".to_owned()]).unwrap(); + let cert_file = cert.pem(); + let key_file = key_pair.serialize_pem(); let cert_file = &mut io::BufReader::new(cert_file.as_bytes()); let key_file = &mut io::BufReader::new(key_file.as_bytes()); diff --git a/actix-http/examples/ws.rs b/actix-http/examples/ws.rs index fac6b136..fb86bc5e 100644 --- a/actix-http/examples/ws.rs +++ b/actix-http/examples/ws.rs @@ -87,9 +87,10 @@ fn tls_config() -> rustls::ServerConfig { use rustls_pemfile::{certs, pkcs8_private_keys}; - 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 rcgen::CertifiedKey { cert, key_pair } = + rcgen::generate_simple_self_signed(["localhost".to_owned()]).unwrap(); + let cert_file = cert.pem(); + let key_file = key_pair.serialize_pem(); let cert_file = &mut BufReader::new(cert_file.as_bytes()); let key_file = &mut BufReader::new(key_file.as_bytes()); diff --git a/actix-http/tests/test_openssl.rs b/actix-http/tests/test_openssl.rs index cb16a4fe..4dd22b58 100644 --- a/actix-http/tests/test_openssl.rs +++ b/actix-http/tests/test_openssl.rs @@ -42,9 +42,11 @@ where } fn tls_config() -> SslAcceptor { - 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 rcgen::CertifiedKey { cert, key_pair } = + rcgen::generate_simple_self_signed(["localhost".to_owned()]).unwrap(); + let cert_file = cert.pem(); + let key_file = key_pair.serialize_pem(); + let cert = X509::from_pem(cert_file.as_bytes()).unwrap(); let key = PKey::private_key_from_pem(key_file.as_bytes()).unwrap(); diff --git a/actix-http/tests/test_rustls.rs b/actix-http/tests/test_rustls.rs index fd2064d5..3ca0d94c 100644 --- a/actix-http/tests/test_rustls.rs +++ b/actix-http/tests/test_rustls.rs @@ -52,9 +52,10 @@ where } fn tls_config() -> RustlsServerConfig { - 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 rcgen::CertifiedKey { cert, key_pair } = + rcgen::generate_simple_self_signed(["localhost".to_owned()]).unwrap(); + let cert_file = cert.pem(); + let key_file = key_pair.serialize_pem(); let cert_file = &mut BufReader::new(cert_file.as_bytes()); let key_file = &mut BufReader::new(key_file.as_bytes()); diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index cd09c305..bd24ea35 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -135,7 +135,7 @@ env_logger = "0.11" flate2 = "1.0.13" futures-util = { version = "0.3.17", default-features = false, features = ["std"] } rand = "0.8" -rcgen = "0.12" +rcgen = "0.13" rustls-pemfile = "2" serde = { version = "1.0", features = ["derive"] } static_assertions = "1" diff --git a/actix-web/tests/test_httpserver.rs b/actix-web/tests/test_httpserver.rs index 86e0575f..039c0ffb 100644 --- a/actix-web/tests/test_httpserver.rs +++ b/actix-web/tests/test_httpserver.rs @@ -64,9 +64,11 @@ fn ssl_acceptor() -> openssl::ssl::SslAcceptorBuilder { x509::X509, }; - 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 rcgen::CertifiedKey { cert, key_pair } = + rcgen::generate_simple_self_signed(["localhost".to_owned()]).unwrap(); + let cert_file = cert.pem(); + let key_file = key_pair.serialize_pem(); + let cert = X509::from_pem(cert_file.as_bytes()).unwrap(); let key = PKey::private_key_from_pem(key_file.as_bytes()).unwrap(); diff --git a/actix-web/tests/test_server.rs b/actix-web/tests/test_server.rs index 60d28235..960cf1e2 100644 --- a/actix-web/tests/test_server.rs +++ b/actix-web/tests/test_server.rs @@ -34,9 +34,11 @@ const STR: &str = const_str::repeat!(S, 100); #[cfg(feature = "openssl")] fn openssl_config() -> SslAcceptor { - 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 rcgen::CertifiedKey { cert, key_pair } = + rcgen::generate_simple_self_signed(["localhost".to_owned()]).unwrap(); + let cert_file = cert.pem(); + let key_file = key_pair.serialize_pem(); + let cert = X509::from_pem(cert_file.as_bytes()).unwrap(); let key = PKey::private_key_from_pem(key_file.as_bytes()).unwrap(); @@ -714,9 +716,10 @@ mod plus_rustls { use super::*; fn tls_config() -> RustlsServerConfig { - 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 rcgen::CertifiedKey { cert, key_pair } = + rcgen::generate_simple_self_signed(["localhost".to_owned()]).unwrap(); + let cert_file = cert.pem(); + let key_file = key_pair.serialize_pem(); let cert_file = &mut BufReader::new(cert_file.as_bytes()); let key_file = &mut BufReader::new(key_file.as_bytes()); diff --git a/awc/Cargo.toml b/awc/Cargo.toml index 2ba8ada3..b1ee6236 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -130,7 +130,7 @@ env_logger = "0.11" flate2 = "1.0.13" futures-util = { version = "0.3.17", default-features = false } static_assertions = "1.1" -rcgen = "0.12" +rcgen = "0.13" rustls-pemfile = "2" tokio = { version = "1.24.2", features = ["rt-multi-thread", "macros"] } zstd = "0.13" diff --git a/awc/tests/test_connector.rs b/awc/tests/test_connector.rs index b3eb9736..a8b7e98c 100644 --- a/awc/tests/test_connector.rs +++ b/awc/tests/test_connector.rs @@ -13,9 +13,11 @@ use openssl::{ }; fn tls_config() -> SslAcceptor { - 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 rcgen::CertifiedKey { cert, key_pair } = + rcgen::generate_simple_self_signed(["localhost".to_owned()]).unwrap(); + let cert_file = cert.pem(); + let key_file = key_pair.serialize_pem(); + let cert = X509::from_pem(cert_file.as_bytes()).unwrap(); let key = PKey::private_key_from_pem(key_file.as_bytes()).unwrap(); diff --git a/awc/tests/test_rustls_client.rs b/awc/tests/test_rustls_client.rs index 719d2511..7e832f67 100644 --- a/awc/tests/test_rustls_client.rs +++ b/awc/tests/test_rustls_client.rs @@ -23,9 +23,10 @@ use rustls::{ use rustls_pemfile::{certs, pkcs8_private_keys}; fn tls_config() -> 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 rcgen::CertifiedKey { cert, key_pair } = + rcgen::generate_simple_self_signed(["localhost".to_owned()]).unwrap(); + let cert_file = cert.pem(); + let key_file = key_pair.serialize_pem(); let cert_file = &mut BufReader::new(cert_file.as_bytes()); let key_file = &mut BufReader::new(key_file.as_bytes()); diff --git a/awc/tests/test_ssl_client.rs b/awc/tests/test_ssl_client.rs index 5273c3ff..95d4c15f 100644 --- a/awc/tests/test_ssl_client.rs +++ b/awc/tests/test_ssl_client.rs @@ -19,9 +19,11 @@ use openssl::{ }; fn tls_config() -> SslAcceptor { - 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 rcgen::CertifiedKey { cert, key_pair } = + rcgen::generate_simple_self_signed(["localhost".to_owned()]).unwrap(); + let cert_file = cert.pem(); + let key_file = key_pair.serialize_pem(); + let cert = X509::from_pem(cert_file.as_bytes()).unwrap(); let key = PKey::private_key_from_pem(key_file.as_bytes()).unwrap(); From fe7268487aa89fe92fac92a547c9fd23dd37508e Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 19 May 2024 10:14:30 +0100 Subject: [PATCH 07/13] chore(actix-http): prepare release 3.7.0 --- actix-http/CHANGES.md | 2 ++ actix-http/Cargo.toml | 2 +- actix-http/README.md | 4 ++-- actix-test/Cargo.toml | 2 +- actix-web/Cargo.toml | 2 +- awc/Cargo.toml | 4 ++-- 6 files changed, 9 insertions(+), 7 deletions(-) diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index f7b20dd6..61eeb4be 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.7.0 + ### Added - Add `rustls-0_23` crate feature diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index c00c2ee0..57509def 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-http" -version = "3.6.0" +version = "3.7.0" authors = [ "Nikolay Kim ", "Rob Ede ", diff --git a/actix-http/README.md b/actix-http/README.md index 3881b805..0ba3fdca 100644 --- a/actix-http/README.md +++ b/actix-http/README.md @@ -5,11 +5,11 @@ [![crates.io](https://img.shields.io/crates/v/actix-http?label=latest)](https://crates.io/crates/actix-http) -[![Documentation](https://docs.rs/actix-http/badge.svg?version=3.6.0)](https://docs.rs/actix-http/3.6.0) +[![Documentation](https://docs.rs/actix-http/badge.svg?version=3.7.0)](https://docs.rs/actix-http/3.7.0) ![Version](https://img.shields.io/badge/rustc-1.72+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-http.svg)
-[![dependency status](https://deps.rs/crate/actix-http/3.6.0/status.svg)](https://deps.rs/crate/actix-http/3.6.0) +[![dependency status](https://deps.rs/crate/actix-http/3.7.0/status.svg)](https://deps.rs/crate/actix-http/3.7.0) [![Download](https://img.shields.io/crates/d/actix-http.svg)](https://crates.io/crates/actix-http) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) diff --git a/actix-test/Cargo.toml b/actix-test/Cargo.toml index 69ce080a..23dde9cf 100644 --- a/actix-test/Cargo.toml +++ b/actix-test/Cargo.toml @@ -37,7 +37,7 @@ openssl = ["tls-openssl", "actix-http/openssl", "awc/openssl"] [dependencies] actix-codec = "0.5" -actix-http = "3.6" +actix-http = "3.7" actix-http-test = "3" actix-rt = "2.1" actix-service = "2" diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index bd24ea35..1faee7a4 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -94,7 +94,7 @@ actix-service = "2" actix-utils = "3" actix-tls = { version = "3.3", default-features = false, optional = true } -actix-http = { version = "3.6", features = ["ws"] } +actix-http = { version = "3.7", features = ["ws"] } actix-router = { version = "0.5", default-features = false, features = ["http"] } actix-web-codegen = { version = "4.2", optional = true } diff --git a/awc/Cargo.toml b/awc/Cargo.toml index b1ee6236..f844db21 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -81,7 +81,7 @@ dangerous-h2c = [] [dependencies] actix-codec = "0.5" actix-service = "2" -actix-http = { version = "3.6", features = ["http2", "ws"] } +actix-http = { version = "3.7", features = ["http2", "ws"] } actix-rt = { version = "2.1", default-features = false } actix-tls = { version = "3.3", features = ["connect", "uri"] } actix-utils = "3" @@ -116,7 +116,7 @@ tls-rustls-0_23 = { package = "rustls", version = "0.23", optional = true, defau trust-dns-resolver = { version = "0.23", optional = true } [dev-dependencies] -actix-http = { version = "3.6", features = ["openssl"] } +actix-http = { version = "3.7", features = ["openssl"] } actix-http-test = { version = "3", features = ["openssl"] } actix-server = "2" actix-test = { version = "0.1", features = ["openssl", "rustls-0_23"] } From 59115bca49bbbb539c6774d613165f424df29a49 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 19 May 2024 10:15:48 +0100 Subject: [PATCH 08/13] chore(actix-web): prepare release 4.6.0 --- actix-test/Cargo.toml | 2 +- actix-web/CHANGES.md | 2 ++ actix-web/Cargo.toml | 2 +- actix-web/README.md | 4 ++-- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/actix-test/Cargo.toml b/actix-test/Cargo.toml index 23dde9cf..3e96f06e 100644 --- a/actix-test/Cargo.toml +++ b/actix-test/Cargo.toml @@ -42,7 +42,7 @@ actix-http-test = "3" actix-rt = "2.1" actix-service = "2" actix-utils = "3" -actix-web = { version = "4.5", default-features = false, features = ["cookies"] } +actix-web = { version = "4.6", default-features = false, features = ["cookies"] } awc = { version = "3.4", default-features = false, features = ["cookies"] } futures-core = { version = "0.3.17", default-features = false, features = ["std"] } diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 5b43a51d..993c7c59 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.6.0 + ### 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. diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index 1faee7a4..cf4da74f 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-web" -version = "4.5.1" +version = "4.6.0" description = "Actix Web is a powerful, pragmatic, and extremely fast web framework for Rust" authors = [ "Nikolay Kim ", diff --git a/actix-web/README.md b/actix-web/README.md index 35e07fc0..4e7e785a 100644 --- a/actix-web/README.md +++ b/actix-web/README.md @@ -8,10 +8,10 @@ [![crates.io](https://img.shields.io/crates/v/actix-web?label=latest)](https://crates.io/crates/actix-web) -[![Documentation](https://docs.rs/actix-web/badge.svg?version=4.5.1)](https://docs.rs/actix-web/4.5.1) +[![Documentation](https://docs.rs/actix-web/badge.svg?version=4.6.0)](https://docs.rs/actix-web/4.6.0) ![MSRV](https://img.shields.io/badge/rustc-1.72+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-web.svg) -[![Dependency Status](https://deps.rs/crate/actix-web/4.5.1/status.svg)](https://deps.rs/crate/actix-web/4.5.1) +[![Dependency Status](https://deps.rs/crate/actix-web/4.6.0/status.svg)](https://deps.rs/crate/actix-web/4.6.0)
[![CI](https://github.com/actix/actix-web/actions/workflows/ci.yml/badge.svg)](https://github.com/actix/actix-web/actions/workflows/ci.yml) [![codecov](https://codecov.io/gh/actix/actix-web/branch/master/graph/badge.svg)](https://codecov.io/gh/actix/actix-web) From 9a437fe8357a74d4ab04e6df1c431d499a334413 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 19 May 2024 10:16:16 +0100 Subject: [PATCH 09/13] chore(awc): prepare release 3.5.0 --- actix-test/Cargo.toml | 2 +- awc/CHANGES.md | 2 ++ awc/Cargo.toml | 2 +- awc/README.md | 4 ++-- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/actix-test/Cargo.toml b/actix-test/Cargo.toml index 3e96f06e..dddcabec 100644 --- a/actix-test/Cargo.toml +++ b/actix-test/Cargo.toml @@ -43,7 +43,7 @@ actix-rt = "2.1" actix-service = "2" actix-utils = "3" actix-web = { version = "4.6", default-features = false, features = ["cookies"] } -awc = { version = "3.4", default-features = false, features = ["cookies"] } +awc = { version = "3.5", default-features = false, features = ["cookies"] } futures-core = { version = "0.3.17", default-features = false, features = ["std"] } futures-util = { version = "0.3.17", default-features = false, features = [] } diff --git a/awc/CHANGES.md b/awc/CHANGES.md index 4031d2bd..54c5e986 100644 --- a/awc/CHANGES.md +++ b/awc/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.5.0 + - Add `rustls-0_23`, `rustls-0_23-webpki-roots`, and `rustls-0_23-native-roots` crate features. - Add `awc::Connector::rustls_0_23()` constructor. - Fix `rustls-0_22-native-roots` root store lookup diff --git a/awc/Cargo.toml b/awc/Cargo.toml index f844db21..58986f3e 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "awc" -version = "3.4.0" +version = "3.5.0" authors = ["Nikolay Kim "] description = "Async HTTP and WebSocket client library" keywords = ["actix", "http", "framework", "async", "web"] diff --git a/awc/README.md b/awc/README.md index 19236b85..8e7b4281 100644 --- a/awc/README.md +++ b/awc/README.md @@ -5,9 +5,9 @@ [![crates.io](https://img.shields.io/crates/v/awc?label=latest)](https://crates.io/crates/awc) -[![Documentation](https://docs.rs/awc/badge.svg?version=3.4.0)](https://docs.rs/awc/3.4.0) +[![Documentation](https://docs.rs/awc/badge.svg?version=3.5.0)](https://docs.rs/awc/3.5.0) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/awc) -[![Dependency Status](https://deps.rs/crate/awc/3.4.0/status.svg)](https://deps.rs/crate/awc/3.4.0) +[![Dependency Status](https://deps.rs/crate/awc/3.5.0/status.svg)](https://deps.rs/crate/awc/3.5.0) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) From acb740584c759499000cc19d322d4f0293389631 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 19 May 2024 11:55:12 +0100 Subject: [PATCH 10/13] fix: correct aws rustls v0.23 feature gating --- actix-http/Cargo.toml | 2 +- actix-web/Cargo.toml | 2 +- awc/Cargo.toml | 4 ++-- awc/src/client/connector.rs | 5 ++++- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index 57509def..a999e73c 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -115,7 +115,7 @@ rand = { version = "0.8", optional = true } sha1 = { version = "0.10", optional = true } # openssl/rustls -actix-tls = { version = "3.3", default-features = false, optional = true } +actix-tls = { version = "3.4", default-features = false, optional = true } # compress-* brotli = { version = "6", optional = true } diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index cf4da74f..32fcc060 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -92,7 +92,7 @@ actix-rt = { version = "2.6", default-features = false } actix-server = "2" actix-service = "2" actix-utils = "3" -actix-tls = { version = "3.3", default-features = false, optional = true } +actix-tls = { version = "3.4", default-features = false, optional = true } actix-http = { version = "3.7", features = ["ws"] } actix-router = { version = "0.5", default-features = false, features = ["http"] } diff --git a/awc/Cargo.toml b/awc/Cargo.toml index 58986f3e..f51b3904 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -83,7 +83,7 @@ actix-codec = "0.5" actix-service = "2" actix-http = { version = "3.7", features = ["http2", "ws"] } actix-rt = { version = "2.1", default-features = false } -actix-tls = { version = "3.3", features = ["connect", "uri"] } +actix-tls = { version = "3.4", features = ["connect", "uri"] } actix-utils = "3" base64 = "0.22" @@ -120,7 +120,7 @@ actix-http = { version = "3.7", features = ["openssl"] } actix-http-test = { version = "3", features = ["openssl"] } actix-server = "2" actix-test = { version = "0.1", features = ["openssl", "rustls-0_23"] } -actix-tls = { version = "3.3", features = ["openssl", "rustls-0_23"] } +actix-tls = { version = "3.4", features = ["openssl", "rustls-0_23"] } actix-utils = "3" actix-web = { version = "4", features = ["openssl"] } diff --git a/awc/src/client/connector.rs b/awc/src/client/connector.rs index fbe50b65..5d0b655a 100644 --- a/awc/src/client/connector.rs +++ b/awc/src/client/connector.rs @@ -131,7 +131,6 @@ impl Connector<()> { OurTlsConnector::Rustls023(std::sync::Arc::new(config)) } - } else if #[cfg(any(feature = "rustls-0_22-webpki-roots", feature = "rustls-0_22-native-roots"))] { /// Build TLS connector with Rustls v0.22, based on supplied ALPN protocols. fn build_tls(protocols: Vec>) -> OurTlsConnector { @@ -743,6 +742,9 @@ where feature = "rustls-0_21", feature = "rustls-0_22-webpki-roots", feature = "rustls-0_22-native-roots", + feature = "rustls-0_23", + feature = "rustls-0_23-webpki-roots", + feature = "rustls-0_23-native-roots" ))] struct TlsConnectorService { /// TCP connection is canceled on `TcpConnectorInnerService`'s timeout setting. @@ -761,6 +763,7 @@ struct TlsConnectorService { feature = "rustls-0_21", feature = "rustls-0_22-webpki-roots", feature = "rustls-0_22-native-roots", + feature = "rustls-0_23", ))] impl Service for TlsConnectorService where From 804a3445658cc946e52632457b2807cac660f2d5 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 19 May 2024 12:06:20 +0100 Subject: [PATCH 11/13] ci: limit cargo hack concurrency --- .cargo/config.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.cargo/config.toml b/.cargo/config.toml index 6d5a8b81..a2345e18 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -6,5 +6,5 @@ lint-all = "clippy --workspace --all-features --all-targets -- -Dclippy::todo" ci-check-min = "hack --workspace check --no-default-features" ci-check-default = "hack --workspace check" ci-check-default-tests = "check --workspace --tests" -ci-check-all-feature-powerset="hack --workspace --feature-powerset --skip=__compress,experimental-io-uring check" -ci-check-all-feature-powerset-linux="hack --workspace --feature-powerset --skip=__compress check" +ci-check-all-feature-powerset="hack --workspace --feature-powerset --depth=4 --skip=__compress,experimental-io-uring check" +ci-check-all-feature-powerset-linux="hack --workspace --feature-powerset --depth=4 --skip=__compress check" From b342b8fc82317365dd9e43659601345d86ba065d Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 19 May 2024 12:09:46 +0100 Subject: [PATCH 12/13] chore(actix-router): prepare release 0.5.3 --- actix-router/CHANGES.md | 2 ++ actix-router/Cargo.toml | 2 +- actix-router/README.md | 4 ++-- actix-web/Cargo.toml | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/actix-router/CHANGES.md b/actix-router/CHANGES.md index 8aa3c863..6305b45c 100644 --- a/actix-router/CHANGES.md +++ b/actix-router/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +## 0.5.3 + - 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. - Minimum supported Rust version (MSRV) is now 1.72. diff --git a/actix-router/Cargo.toml b/actix-router/Cargo.toml index 0b02e84b..56e4bed2 100644 --- a/actix-router/Cargo.toml +++ b/actix-router/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-router" -version = "0.5.2" +version = "0.5.3" authors = [ "Nikolay Kim ", "Ali MJ Al-Nasrawy ", diff --git a/actix-router/README.md b/actix-router/README.md index 751c307b..12d1b014 100644 --- a/actix-router/README.md +++ b/actix-router/README.md @@ -3,11 +3,11 @@ [![crates.io](https://img.shields.io/crates/v/actix-router?label=latest)](https://crates.io/crates/actix-router) -[![Documentation](https://docs.rs/actix-router/badge.svg?version=0.5.2)](https://docs.rs/actix-router/0.5.2) +[![Documentation](https://docs.rs/actix-router/badge.svg?version=0.5.3)](https://docs.rs/actix-router/0.5.3) ![Version](https://img.shields.io/badge/rustc-1.72+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-router.svg)
-[![dependency status](https://deps.rs/crate/actix-router/0.5.2/status.svg)](https://deps.rs/crate/actix-router/0.5.2) +[![dependency status](https://deps.rs/crate/actix-router/0.5.3/status.svg)](https://deps.rs/crate/actix-router/0.5.3) [![Download](https://img.shields.io/crates/d/actix-router.svg)](https://crates.io/crates/actix-router) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index 32fcc060..9f3ab6e5 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -95,7 +95,7 @@ actix-utils = "3" actix-tls = { version = "3.4", default-features = false, optional = true } actix-http = { version = "3.7", features = ["ws"] } -actix-router = { version = "0.5", default-features = false, features = ["http"] } +actix-router = { version = "0.5.3", default-features = false, features = ["http"] } actix-web-codegen = { version = "4.2", optional = true } ahash = "0.8" From fdff3775a8625588d7a55a8ec0ad471308f4ae6f Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 19 May 2024 20:24:33 +0100 Subject: [PATCH 13/13] ci: use mold linker (#3370) --- .github/workflows/ci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 56333e18..a81f0e8e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -54,6 +54,10 @@ jobs: echo 'OPENSSL_DIR=C:\Program Files\OpenSSL' >> $GITHUB_ENV echo "RUSTFLAGS=-C target-feature=+crt-static" >> $GITHUB_ENV + - name: Setup mold linker + if: matrix.target.os == 'ubuntu-latest' + uses: rui314/setup-mold@v1 + - name: Install Rust (${{ matrix.version.name }}) uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 with: