diff --git a/.cargo/config.toml b/.cargo/config.toml
index 931b20b2c..350a924de 100644
--- a/.cargo/config.toml
+++ b/.cargo/config.toml
@@ -1,6 +1,6 @@
[alias]
-lint = "clippy --workspace --tests --examples --bins -- -Dclippy::todo"
-lint-all = "clippy --workspace --all-features --tests --examples --bins -- -Dclippy::todo"
+lint = "clippy --workspace --all-targets -- -Dclippy::todo"
+lint-all = "clippy --workspace --all-features --all-targets -- -Dclippy::todo"
# lib checking
ci-check-min = "hack --workspace check --no-default-features"
diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml
index e63821892..1a0437cbe 100644
--- a/.github/workflows/ci-post-merge.yml
+++ b/.github/workflows/ci-post-merge.yml
@@ -32,22 +32,22 @@ jobs:
- name: Install OpenSSL
if: matrix.target.os == 'windows-latest'
- run: choco install openssl -y --forcex64 --no-progress
- - name: Set OpenSSL dir in env
- if: matrix.target.os == 'windows-latest'
+ shell: bash
run: |
- echo 'OPENSSL_DIR=C:\Program Files\OpenSSL-Win64' | Out-File -FilePath $env:GITHUB_ENV -Append
- echo 'OPENSSL_DIR=C:\Program Files\OpenSSL' | Out-File -FilePath $env:GITHUB_ENV -Append
+ set -e
+ choco install openssl --version=1.1.1.2100 -y --no-progress
+ echo 'OPENSSL_DIR=C:\Program Files\OpenSSL' >> $GITHUB_ENV
+ echo "RUSTFLAGS=-C target-feature=+crt-static" >> $GITHUB_ENV
- name: Install Rust (${{ matrix.version.name }})
uses: actions-rust-lang/setup-rust-toolchain@v1.8.0
with:
toolchain: ${{ matrix.version.version }}
- - name: Install cargo-hack
- uses: taiki-e/install-action@v2.25.9
+ - name: Install cargo-hack and cargo-ci-cache-clean
+ uses: taiki-e/install-action@v2.26.12
with:
- tool: cargo-hack
+ tool: cargo-hack,cargo-ci-cache-clean
- name: check minimal
run: cargo ci-check-min
@@ -57,10 +57,12 @@ jobs:
- name: tests
timeout-minutes: 60
+ shell: bash
run: |
+ set -e
cargo test --lib --tests -p=actix-router --all-features
cargo test --lib --tests -p=actix-http --all-features
- cargo test --lib --tests -p=actix-web --features=rustls-0_20,rustls-0_21,openssl -- --skip=test_reading_deflate_encoding_large_random_rustls
+ cargo test --lib --tests -p=actix-web --features=rustls-0_20,rustls-0_21,rustls-0_22,openssl -- --skip=test_reading_deflate_encoding_large_random_rustls
cargo test --lib --tests -p=actix-web-codegen --all-features
cargo test --lib --tests -p=awc --all-features
cargo test --lib --tests -p=actix-http-test --all-features
@@ -69,10 +71,8 @@ jobs:
cargo test --lib --tests -p=actix-multipart --all-features
cargo test --lib --tests -p=actix-web-actors --all-features
- - name: Clear the cargo caches
- run: |
- cargo --locked install cargo-cache --version 0.8.3 --no-default-features --features ci-autoclean
- cargo-cache
+ - name: CI cache clean
+ run: cargo-ci-cache-clean
ci_feature_powerset_check:
name: Verify Feature Combinations
@@ -85,7 +85,7 @@ jobs:
uses: actions-rust-lang/setup-rust-toolchain@v1.8.0
- name: Install cargo-hack
- uses: taiki-e/install-action@v2.25.9
+ uses: taiki-e/install-action@v2.26.12
with:
tool: cargo-hack
@@ -106,7 +106,7 @@ jobs:
uses: actions-rust-lang/setup-rust-toolchain@v1.8.0
- name: Install nextest
- uses: taiki-e/install-action@v2.25.9
+ uses: taiki-e/install-action@v2.26.12
with:
tool: nextest
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 9dcd8fab9..915eb7eae 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -26,7 +26,7 @@ jobs:
- { name: macOS, os: macos-latest, triple: x86_64-apple-darwin }
- { name: Windows, os: windows-latest, triple: x86_64-pc-windows-msvc }
version:
- - { name: msrv, version: 1.68.0 }
+ - { name: msrv, version: 1.72.0 }
- { name: stable, version: stable }
name: ${{ matrix.target.name }} / ${{ matrix.version.name }}
@@ -37,29 +37,27 @@ jobs:
- name: Install OpenSSL
if: matrix.target.os == 'windows-latest'
- run: choco install openssl -y --forcex64 --no-progress
- - name: Set OpenSSL dir in env
- if: matrix.target.os == 'windows-latest'
+ shell: bash
run: |
- echo 'OPENSSL_DIR=C:\Program Files\OpenSSL-Win64' | Out-File -FilePath $env:GITHUB_ENV -Append
- echo 'OPENSSL_DIR=C:\Program Files\OpenSSL' | Out-File -FilePath $env:GITHUB_ENV -Append
+ set -e
+ choco install openssl --version=1.1.1.2100 -y --no-progress
+ echo 'OPENSSL_DIR=C:\Program Files\OpenSSL' >> $GITHUB_ENV
+ echo "RUSTFLAGS=-C target-feature=+crt-static" >> $GITHUB_ENV
- name: Install Rust (${{ matrix.version.name }})
uses: actions-rust-lang/setup-rust-toolchain@v1.8.0
with:
toolchain: ${{ matrix.version.version }}
- - name: Install cargo-hack
- uses: taiki-e/install-action@v2.25.9
+ - name: Install cargo-hack and cargo-ci-cache-clean
+ uses: taiki-e/install-action@v2.26.12
with:
- tool: cargo-hack
+ tool: cargo-hack,cargo-ci-cache-clean
- name: workaround MSRV issues
if: matrix.version.name == 'msrv'
run: |
- cargo update -p=clap --precise=4.3.24
- cargo update -p=clap_lex --precise=0.5.0
- cargo update -p=anstyle --precise=1.0.2
+ cargo update -p=clap --precise=4.4.18
- name: check minimal
run: cargo ci-check-min
@@ -69,10 +67,12 @@ jobs:
- name: tests
timeout-minutes: 60
+ shell: bash
run: |
+ set -e
cargo test --lib --tests -p=actix-router --all-features
cargo test --lib --tests -p=actix-http --all-features
- cargo test --lib --tests -p=actix-web --features=rustls-0_20,rustls-0_21,openssl -- --skip=test_reading_deflate_encoding_large_random_rustls
+ cargo test --lib --tests -p=actix-web --features=rustls-0_20,rustls-0_21,rustls-0_22,openssl -- --skip=test_reading_deflate_encoding_large_random_rustls
cargo test --lib --tests -p=actix-web-codegen --all-features
cargo test --lib --tests -p=awc --all-features
cargo test --lib --tests -p=actix-http-test --all-features
@@ -81,10 +81,8 @@ jobs:
cargo test --lib --tests -p=actix-multipart --all-features
cargo test --lib --tests -p=actix-web-actors --all-features
- - name: Clear the cargo caches
- run: |
- cargo --locked install cargo-cache --version 0.8.3 --no-default-features --features ci-autoclean
- cargo-cache
+ - name: CI cache clean
+ run: cargo-ci-cache-clean
io-uring:
name: io-uring tests
diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml
index 2722da084..180a9a0e0 100644
--- a/.github/workflows/coverage.yml
+++ b/.github/workflows/coverage.yml
@@ -23,7 +23,7 @@ jobs:
components: llvm-tools-preview
- name: Install cargo-llvm-cov
- uses: taiki-e/install-action@v2.25.9
+ uses: taiki-e/install-action@v2.26.12
with:
tool: cargo-llvm-cov
@@ -31,7 +31,9 @@ jobs:
run: cargo llvm-cov --workspace --all-features --codecov --output-path codecov.json
- name: Upload coverage to Codecov
- uses: codecov/codecov-action@v3.1.4
+ uses: codecov/codecov-action@v4.0.1
with:
files: codecov.json
fail_ci_if_error: true
+ env:
+ CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index adcb257b5..bb03acce2 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -82,7 +82,7 @@ jobs:
toolchain: nightly-2023-08-25
- name: Install cargo-public-api
- uses: taiki-e/install-action@v2.24.1
+ uses: taiki-e/install-action@v2.26.12
with:
tool: cargo-public-api
diff --git a/Cargo.toml b/Cargo.toml
index 58fd96935..9efeda4d1 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -17,7 +17,7 @@ members = [
[workspace.package]
license = "MIT OR Apache-2.0"
edition = "2021"
-rust-version = "1.68"
+rust-version = "1.72"
[profile.dev]
# Disabling debug info speeds up builds a bunch and we don't rely on it for debugging that much.
diff --git a/actix-files/CHANGES.md b/actix-files/CHANGES.md
index 9aa62ff77..393e7b61a 100644
--- a/actix-files/CHANGES.md
+++ b/actix-files/CHANGES.md
@@ -2,6 +2,8 @@
## Unreleased
+- Minimum supported Rust version (MSRV) is now 1.72.
+
## 0.6.5
- Fix handling of special characters in filenames.
diff --git a/actix-files/README.md b/actix-files/README.md
index df80e4047..a6b3f63c6 100644
--- a/actix-files/README.md
+++ b/actix-files/README.md
@@ -4,7 +4,7 @@
[![crates.io](https://img.shields.io/crates/v/actix-files?label=latest)](https://crates.io/crates/actix-files)
[![Documentation](https://docs.rs/actix-files/badge.svg?version=0.6.5)](https://docs.rs/actix-files/0.6.5)
-![Version](https://img.shields.io/badge/rustc-1.68+-ab6000.svg)
+![Version](https://img.shields.io/badge/rustc-1.72+-ab6000.svg)
![License](https://img.shields.io/crates/l/actix-files.svg)
[![dependency status](https://deps.rs/crate/actix-files/0.6.5/status.svg)](https://deps.rs/crate/actix-files/0.6.5)
diff --git a/actix-files/src/lib.rs b/actix-files/src/lib.rs
index 5b1f14eed..8381519aa 100644
--- a/actix-files/src/lib.rs
+++ b/actix-files/src/lib.rs
@@ -568,6 +568,7 @@ mod tests {
assert_eq!(bytes, data);
}
+ #[cfg(not(target_os = "windows"))]
#[actix_rt::test]
async fn test_static_files_with_special_characters() {
// Create the file we want to test against ad-hoc. We can't check it in as otherwise
diff --git a/actix-http-test/CHANGES.md b/actix-http-test/CHANGES.md
index 065141b20..4d133e3ec 100644
--- a/actix-http-test/CHANGES.md
+++ b/actix-http-test/CHANGES.md
@@ -2,6 +2,10 @@
## Unreleased
+- Minimum supported Rust version (MSRV) is now 1.72.
+
+## 3.2.0
+
- Minimum supported Rust version (MSRV) is now 1.68 due to transitive `time` dependency.
## 3.1.0
diff --git a/actix-http-test/Cargo.toml b/actix-http-test/Cargo.toml
index 0881e0bc4..bfb0a3539 100644
--- a/actix-http-test/Cargo.toml
+++ b/actix-http-test/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "actix-http-test"
-version = "3.1.0"
+version = "3.2.0"
authors = ["Nikolay Kim "]
description = "Various helpers for Actix applications to use during testing"
keywords = ["http", "web", "framework", "async", "futures"]
diff --git a/actix-http-test/README.md b/actix-http-test/README.md
index e544c3616..ee242d1d5 100644
--- a/actix-http-test/README.md
+++ b/actix-http-test/README.md
@@ -5,17 +5,12 @@
[![crates.io](https://img.shields.io/crates/v/actix-http-test?label=latest)](https://crates.io/crates/actix-http-test)
-[![Documentation](https://docs.rs/actix-http-test/badge.svg?version=3.1.0)](https://docs.rs/actix-http-test/3.1.0)
-![Version](https://img.shields.io/badge/rustc-1.68+-ab6000.svg)
+[![Documentation](https://docs.rs/actix-http-test/badge.svg?version=3.2.0)](https://docs.rs/actix-http-test/3.2.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-test)
-[![Dependency Status](https://deps.rs/crate/actix-http-test/3.1.0/status.svg)](https://deps.rs/crate/actix-http-test/3.1.0)
+[![Dependency Status](https://deps.rs/crate/actix-http-test/3.2.0/status.svg)](https://deps.rs/crate/actix-http-test/3.2.0)
[![Download](https://img.shields.io/crates/d/actix-http-test.svg)](https://crates.io/crates/actix-http-test)
[![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x)
-
-## Documentation & Resources
-
-- [API Documentation](https://docs.rs/actix-http-test)
-- Minimum Supported Rust Version (MSRV): 1.68
diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md
index 994c91a83..fddd1c2c3 100644
--- a/actix-http/CHANGES.md
+++ b/actix-http/CHANGES.md
@@ -2,6 +2,18 @@
## Unreleased
+### Changed
+
+- Minimum supported Rust version (MSRV) is now 1.72.
+
+## 3.6.0
+
+### Added
+
+- Add `rustls-0_22` crate feature.
+- Add `{h1::H1Service, h2::H2Service, HttpService}::rustls_0_22()` and `HttpService::rustls_0_22_with_config()` service constructors.
+- Implement `From<&HeaderMap>` for `http::HeaderMap`.
+
## 3.5.1
### Fixed
diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml
index e7d50c313..e8f315cb9 100644
--- a/actix-http/Cargo.toml
+++ b/actix-http/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "actix-http"
-version = "3.5.1"
+version = "3.6.0"
authors = [
"Nikolay Kim ",
"Rob Ede ",
@@ -20,8 +20,18 @@ edition.workspace = true
rust-version.workspace = true
[package.metadata.docs.rs]
-# features that docs.rs will build with
-features = ["http2", "ws", "openssl", "rustls-0_20", "rustls-0_21", "compress-brotli", "compress-gzip", "compress-zstd"]
+rustdoc-args = ["--cfg", "docsrs"]
+features = [
+ "http2",
+ "ws",
+ "openssl",
+ "rustls-0_20",
+ "rustls-0_21",
+ "rustls-0_22",
+ "compress-brotli",
+ "compress-gzip",
+ "compress-zstd",
+]
[lib]
name = "actix_http"
@@ -53,6 +63,9 @@ rustls-0_20 = ["actix-tls/accept", "actix-tls/rustls-0_20"]
# TLS via Rustls v0.21
rustls-0_21 = ["actix-tls/accept", "actix-tls/rustls-0_21"]
+# TLS via Rustls v0.22
+rustls-0_22 = ["actix-tls/accept", "actix-tls/rustls-0_22"]
+
# Compression codecs
compress-brotli = ["__compress", "brotli"]
compress-gzip = ["__compress", "flate2"]
@@ -98,7 +111,7 @@ rand = { version = "0.8", optional = true }
sha1 = { version = "0.10", optional = true }
# openssl/rustls
-actix-tls = { version = "3.1", default-features = false, optional = true }
+actix-tls = { version = "3.3", default-features = false, optional = true }
# compress-*
brotli = { version = "3.3.3", optional = true }
@@ -108,35 +121,40 @@ zstd = { version = "0.13", optional = true }
[dev-dependencies]
actix-http-test = { version = "3", features = ["openssl"] }
actix-server = "2"
-actix-tls = { version = "3.1", features = ["openssl"] }
+actix-tls = { version = "3.3", features = ["openssl", "rustls-0_22-webpki-roots"] }
actix-web = "4"
async-stream = "0.3"
criterion = { version = "0.5", features = ["html_reports"] }
+divan = "0.1.8"
env_logger = "0.10"
futures-util = { version = "0.3.17", default-features = false, features = ["alloc"] }
memchr = "2.4"
once_cell = "1.9"
-rcgen = "0.11"
+rcgen = "0.12"
regex = "1.3"
rustversion = "1"
-rustls-pemfile = "1"
+rustls-pemfile = "2"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
static_assertions = "1"
tls-openssl = { package = "openssl", version = "0.10.55" }
-tls-rustls_021 = { package = "rustls", version = "0.21" }
+tls-rustls_022 = { package = "rustls", version = "0.22" }
tokio = { version = "1.24.2", features = ["net", "rt", "macros"] }
[[example]]
name = "ws"
-required-features = ["ws", "rustls-0_21"]
+required-features = ["ws", "rustls-0_22"]
[[example]]
name = "tls_rustls"
-required-features = ["http2", "rustls-0_21"]
+required-features = ["http2", "rustls-0_22"]
[[bench]]
name = "response-body-compression"
harness = false
required-features = ["compress-brotli", "compress-gzip", "compress-zstd"]
+
+[[bench]]
+name = "date-formatting"
+harness = false
diff --git a/actix-http/README.md b/actix-http/README.md
index 9d80c10c4..3881b805d 100644
--- a/actix-http/README.md
+++ b/actix-http/README.md
@@ -5,21 +5,16 @@
[![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.5.1)](https://docs.rs/actix-http/3.5.1)
-![Version](https://img.shields.io/badge/rustc-1.68+-ab6000.svg)
+[![Documentation](https://docs.rs/actix-http/badge.svg?version=3.6.0)](https://docs.rs/actix-http/3.6.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.5.1/status.svg)](https://deps.rs/crate/actix-http/3.5.1)
+[![dependency status](https://deps.rs/crate/actix-http/3.6.0/status.svg)](https://deps.rs/crate/actix-http/3.6.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)
-## Documentation & Resources
-
-- [API Documentation](https://docs.rs/actix-http)
-- Minimum Supported Rust Version (MSRV): 1.68
-
## Examples
```rust
diff --git a/actix-http/benches/date-formatting.rs b/actix-http/benches/date-formatting.rs
new file mode 100644
index 000000000..26d0f3daa
--- /dev/null
+++ b/actix-http/benches/date-formatting.rs
@@ -0,0 +1,20 @@
+use std::time::SystemTime;
+
+use actix_http::header::HttpDate;
+use divan::{black_box, AllocProfiler, Bencher};
+
+#[global_allocator]
+static ALLOC: AllocProfiler = AllocProfiler::system();
+
+#[divan::bench]
+fn date_formatting(b: Bencher<'_, '_>) {
+ let now = SystemTime::now();
+
+ b.bench(|| {
+ black_box(HttpDate::from(black_box(now)).to_string());
+ })
+}
+
+fn main() {
+ divan::main();
+}
diff --git a/actix-http/examples/h2c-detect.rs b/actix-http/examples/h2c-detect.rs
index aa3dd5d31..b0bde3fe6 100644
--- a/actix-http/examples/h2c-detect.rs
+++ b/actix-http/examples/h2c-detect.rs
@@ -8,7 +8,7 @@
use std::{convert::Infallible, io};
-use actix_http::{HttpService, Request, Response, StatusCode};
+use actix_http::{body::BodyStream, HttpService, Request, Response, StatusCode};
use actix_server::Server;
#[tokio::main(flavor = "current_thread")]
@@ -19,7 +19,12 @@ async fn main() -> io::Result<()> {
.bind("h2c-detect", ("127.0.0.1", 8080), || {
HttpService::build()
.finish(|_req: Request| async move {
- Ok::<_, Infallible>(Response::build(StatusCode::OK).body("Hello!"))
+ Ok::<_, Infallible>(Response::build(StatusCode::OK).body(BodyStream::new(
+ futures_util::stream::iter([
+ Ok::<_, String>("123".into()),
+ Err("wertyuikmnbvcxdfty6t".to_owned()),
+ ]),
+ )))
})
.tcp_auto_h2c()
})?
diff --git a/actix-http/examples/tls_rustls.rs b/actix-http/examples/tls_rustls.rs
index fbb55c6a4..47ff061cd 100644
--- a/actix-http/examples/tls_rustls.rs
+++ b/actix-http/examples/tls_rustls.rs
@@ -12,7 +12,7 @@
//! Protocol: HTTP/1.1
//! ```
-extern crate tls_rustls_021 as rustls;
+extern crate tls_rustls_022 as rustls;
use std::io;
@@ -36,7 +36,7 @@ async fn main() -> io::Result<()> {
);
ok::<_, Error>(Response::ok().set_body(body))
})
- .rustls_021(rustls_config())
+ .rustls_0_22(rustls_config())
})?
.run()
.await
@@ -51,16 +51,18 @@ fn rustls_config() -> rustls::ServerConfig {
let key_file = &mut io::BufReader::new(key_file.as_bytes());
let cert_chain = rustls_pemfile::certs(cert_file)
- .unwrap()
- .into_iter()
- .map(rustls::Certificate)
- .collect();
- let mut keys = rustls_pemfile::pkcs8_private_keys(key_file).unwrap();
+ .collect::, _>>()
+ .unwrap();
+ let mut keys = rustls_pemfile::pkcs8_private_keys(key_file)
+ .collect::, _>>()
+ .unwrap();
let mut config = rustls::ServerConfig::builder()
- .with_safe_defaults()
.with_no_client_auth()
- .with_single_cert(cert_chain, rustls::PrivateKey(keys.remove(0)))
+ .with_single_cert(
+ cert_chain,
+ rustls::pki_types::PrivateKeyDer::Pkcs8(keys.remove(0)),
+ )
.unwrap();
const H1_ALPN: &[u8] = b"http/1.1";
diff --git a/actix-http/examples/ws.rs b/actix-http/examples/ws.rs
index 241175ae2..55085fd73 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_021 as rustls;
+extern crate tls_rustls_022 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_021(tls_config())
+ .rustls_0_22(tls_config())
})?
.run()
.await
@@ -85,7 +85,6 @@ impl Stream for Heartbeat {
fn tls_config() -> rustls::ServerConfig {
use std::io::BufReader;
- use rustls::{Certificate, PrivateKey};
use rustls_pemfile::{certs, pkcs8_private_keys};
let cert = rcgen::generate_simple_self_signed(vec!["localhost".to_owned()]).unwrap();
@@ -95,17 +94,17 @@ fn tls_config() -> rustls::ServerConfig {
let cert_file = &mut BufReader::new(cert_file.as_bytes());
let key_file = &mut BufReader::new(key_file.as_bytes());
- let cert_chain = certs(cert_file)
- .unwrap()
- .into_iter()
- .map(Certificate)
- .collect();
- let mut keys = pkcs8_private_keys(key_file).unwrap();
+ let cert_chain = certs(cert_file).collect::, _>>().unwrap();
+ let mut keys = pkcs8_private_keys(key_file)
+ .collect::, _>>()
+ .unwrap();
let mut config = rustls::ServerConfig::builder()
- .with_safe_defaults()
.with_no_client_auth()
- .with_single_cert(cert_chain, PrivateKey(keys.remove(0)))
+ .with_single_cert(
+ cert_chain,
+ rustls::pki_types::PrivateKeyDer::Pkcs8(keys.remove(0)),
+ )
.unwrap();
config.alpn_protocols.push(b"http/1.1".to_vec());
diff --git a/actix-http/src/date.rs b/actix-http/src/date.rs
index 1358bbd8c..735dd9100 100644
--- a/actix-http/src/date.rs
+++ b/actix-http/src/date.rs
@@ -28,7 +28,7 @@ impl Date {
fn update(&mut self) {
self.pos = 0;
- write!(self, "{}", httpdate::fmt_http_date(SystemTime::now())).unwrap();
+ write!(self, "{}", httpdate::HttpDate::from(SystemTime::now())).unwrap();
}
}
diff --git a/actix-http/src/h1/dispatcher.rs b/actix-http/src/h1/dispatcher.rs
index 270707807..a24a6bb07 100644
--- a/actix-http/src/h1/dispatcher.rs
+++ b/actix-http/src/h1/dispatcher.rs
@@ -512,8 +512,10 @@ where
}
Poll::Ready(Some(Err(err))) => {
+ let err = err.into();
+ tracing::error!("Response payload stream error: {err:?}");
this.flags.insert(Flags::FINISHED);
- return Err(DispatchError::Body(err.into()));
+ return Err(DispatchError::Body(err));
}
Poll::Pending => return Ok(PollResponse::DoNothing),
@@ -549,6 +551,7 @@ where
}
Poll::Ready(Some(Err(err))) => {
+ tracing::error!("Response payload stream error: {err:?}");
this.flags.insert(Flags::FINISHED);
return Err(DispatchError::Body(
Error::new_body().with_cause(err).into(),
@@ -703,7 +706,7 @@ where
req.head_mut().peer_addr = *this.peer_addr;
- req.conn_data = this.conn_data.as_ref().map(Rc::clone);
+ req.conn_data = this.conn_data.clone();
match this.codec.message_type() {
// request has no payload
diff --git a/actix-http/src/h1/service.rs b/actix-http/src/h1/service.rs
index 3b27e3db5..64eb39c82 100644
--- a/actix-http/src/h1/service.rs
+++ b/actix-http/src/h1/service.rs
@@ -153,7 +153,7 @@ mod openssl {
}
#[cfg(feature = "rustls-0_20")]
-mod rustls_020 {
+mod rustls_0_20 {
use std::io;
use actix_service::ServiceFactoryExt as _;
@@ -214,7 +214,7 @@ mod rustls_020 {
}
#[cfg(feature = "rustls-0_21")]
-mod rustls_021 {
+mod rustls_0_21 {
use std::io;
use actix_service::ServiceFactoryExt as _;
@@ -274,6 +274,67 @@ mod rustls_021 {
}
}
+#[cfg(feature = "rustls-0_22")]
+mod rustls_0_22 {
+ use std::io;
+
+ use actix_service::ServiceFactoryExt as _;
+ use actix_tls::accept::{
+ rustls_0_22::{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.22 based service.
+ pub fn rustls_0_22(
+ 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/dispatcher.rs b/actix-http/src/h2/dispatcher.rs
index 3e618820e..97ceb51e9 100644
--- a/actix-http/src/h2/dispatcher.rs
+++ b/actix-http/src/h2/dispatcher.rs
@@ -4,7 +4,7 @@ use std::{
future::Future,
marker::PhantomData,
net,
- pin::Pin,
+ pin::{pin, Pin},
rc::Rc,
task::{Context, Poll},
};
@@ -20,7 +20,6 @@ use h2::{
Ping, PingPong,
};
use pin_project_lite::pin_project;
-use tracing::{error, trace, warn};
use crate::{
body::{BodySize, BoxBody, MessageBody},
@@ -127,7 +126,7 @@ where
head.headers = parts.headers.into();
head.peer_addr = this.peer_addr;
- req.conn_data = this.conn_data.as_ref().map(Rc::clone);
+ req.conn_data = this.conn_data.clone();
let fut = this.flow.service.call(req);
let config = this.config.clone();
@@ -147,11 +146,13 @@ where
if let Err(err) = res {
match err {
DispatchError::SendResponse(err) => {
- trace!("Error sending HTTP/2 response: {:?}", err)
+ tracing::trace!("Error sending response: {err:?}");
+ }
+ DispatchError::SendData(err) => {
+ tracing::warn!("Send data error: {err:?}");
}
- DispatchError::SendData(err) => warn!("{:?}", err),
DispatchError::ResponseBody(err) => {
- error!("Response payload stream error: {:?}", err)
+ tracing::error!("Response payload stream error: {err:?}");
}
}
}
@@ -228,9 +229,9 @@ where
return Ok(());
}
- // poll response body and send chunks to client
- actix_rt::pin!(body);
+ let mut body = pin!(body);
+ // poll response body and send chunks to client
while let Some(res) = poll_fn(|cx| body.as_mut().poll_next(cx)).await {
let mut chunk = res.map_err(|err| DispatchError::ResponseBody(err.into()))?;
diff --git a/actix-http/src/h2/service.rs b/actix-http/src/h2/service.rs
index 0ae7ea682..d50ffc4e3 100644
--- a/actix-http/src/h2/service.rs
+++ b/actix-http/src/h2/service.rs
@@ -141,7 +141,7 @@ mod openssl {
}
#[cfg(feature = "rustls-0_20")]
-mod rustls_020 {
+mod rustls_0_20 {
use std::io;
use actix_service::ServiceFactoryExt as _;
@@ -192,7 +192,7 @@ mod rustls_020 {
}
#[cfg(feature = "rustls-0_21")]
-mod rustls_021 {
+mod rustls_0_21 {
use std::io;
use actix_service::ServiceFactoryExt as _;
@@ -242,6 +242,57 @@ mod rustls_021 {
}
}
+#[cfg(feature = "rustls-0_22")]
+mod rustls_0_22 {
+ use std::io;
+
+ use actix_service::ServiceFactoryExt as _;
+ use actix_tls::accept::{
+ rustls_0_22::{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.22 based service.
+ pub fn rustls_0_22(
+ 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/header/map.rs b/actix-http/src/header/map.rs
index d8a63b573..b86798a4c 100644
--- a/actix-http/src/header/map.rs
+++ b/actix-http/src/header/map.rs
@@ -650,6 +650,13 @@ impl From for http::HeaderMap {
}
}
+/// Convert our `&HeaderMap` to a `http::HeaderMap`.
+impl From<&HeaderMap> for http::HeaderMap {
+ fn from(map: &HeaderMap) -> Self {
+ map.to_owned().into()
+ }
+}
+
/// Iterator over removed, owned values with the same associated name.
///
/// Returned from methods that remove or replace items. See [`HeaderMap::insert`]
diff --git a/actix-http/src/header/shared/http_date.rs b/actix-http/src/header/shared/http_date.rs
index 21ed49f0c..bdfbc7051 100644
--- a/actix-http/src/header/shared/http_date.rs
+++ b/actix-http/src/header/shared/http_date.rs
@@ -24,8 +24,7 @@ impl FromStr for HttpDate {
impl fmt::Display for HttpDate {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- let date_str = httpdate::fmt_http_date(self.0);
- f.write_str(&date_str)
+ httpdate::HttpDate::from(self.0).fmt(f)
}
}
@@ -37,7 +36,7 @@ impl TryIntoHeaderValue for HttpDate {
let mut wrt = MutWriter(&mut buf);
// unwrap: date output is known to be well formed and of known length
- write!(wrt, "{}", httpdate::fmt_http_date(self.0)).unwrap();
+ write!(wrt, "{}", self).unwrap();
HeaderValue::from_maybe_shared(buf.split().freeze())
}
diff --git a/actix-http/src/header/utils.rs b/actix-http/src/header/utils.rs
index f4f34d347..caaab3b1e 100644
--- a/actix-http/src/header/utils.rs
+++ b/actix-http/src/header/utils.rs
@@ -80,18 +80,18 @@ mod tests {
#[test]
fn comma_delimited_parsing() {
- let headers = vec![];
+ let headers = [];
let res: Vec = from_comma_delimited(headers.iter()).unwrap();
assert_eq!(res, vec![0; 0]);
- let headers = vec![
+ let headers = [
HeaderValue::from_static("1, 2"),
HeaderValue::from_static("3,4"),
];
let res: Vec = from_comma_delimited(headers.iter()).unwrap();
assert_eq!(res, vec![1, 2, 3, 4]);
- let headers = vec![
+ let headers = [
HeaderValue::from_static(""),
HeaderValue::from_static(","),
HeaderValue::from_static(" "),
diff --git a/actix-http/src/lib.rs b/actix-http/src/lib.rs
index 888c3e06f..cb82ced00 100644
--- a/actix-http/src/lib.rs
+++ b/actix-http/src/lib.rs
@@ -58,7 +58,12 @@ pub mod ws;
#[allow(deprecated)]
pub use self::payload::PayloadStream;
-#[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",
+))]
pub use self::service::TlsAcceptorConfig;
pub use self::{
builder::HttpServiceBuilder,
diff --git a/actix-http/src/notify_on_drop.rs b/actix-http/src/notify_on_drop.rs
index 98544bb5d..95904b28e 100644
--- a/actix-http/src/notify_on_drop.rs
+++ b/actix-http/src/notify_on_drop.rs
@@ -5,7 +5,7 @@
use std::cell::RefCell;
thread_local! {
- static NOTIFY_DROPPED: RefCell