From 7fc73d58a9de68f0dfcc809d263dc1ffea20da28 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Thu, 2 May 2024 03:22:13 +0100 Subject: [PATCH 01/63] ci: fix public api --- .github/workflows/lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index b0ac537a2..a10c2411a 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -79,7 +79,7 @@ jobs: - name: Install Rust uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 with: - toolchain: nightly-2023-08-25 + toolchain: nightly-2024-04-26 - name: Install cargo-public-api uses: taiki-e/install-action@v2.32.17 From 7f15a95d8e15c3b09f64a301aa33ac89a82863a2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 May 2024 03:22:59 +0100 Subject: [PATCH 02/63] build(deps): bump JamesIves/github-pages-deploy-action from 4.5.0 to 4.6.0 (#3339) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/upload-doc.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/upload-doc.yml b/.github/workflows/upload-doc.yml index 963b7f6b3..6352e44d2 100644 --- a/.github/workflows/upload-doc.yml +++ b/.github/workflows/upload-doc.yml @@ -35,7 +35,7 @@ jobs: run: echo '' > target/doc/index.html - name: Deploy to GitHub Pages - uses: JamesIves/github-pages-deploy-action@v4.5.0 + uses: JamesIves/github-pages-deploy-action@v4.6.0 with: folder: target/doc single-commit: true From babac131d4bf2f9d8e343a77ff75d496a5249d10 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 May 2024 02:39:28 +0000 Subject: [PATCH 03/63] build(deps): bump taiki-e/install-action from 2.32.17 to 2.33.12 (#3347) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.32.17 to 2.33.12. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/v2.32.17...v2.33.12) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 6 +++--- .github/workflows/ci.yml | 2 +- .github/workflows/coverage.yml | 2 +- .github/workflows/lint.yml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index 55202ba6c..10670ab34 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -45,7 +45,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack and cargo-ci-cache-clean - uses: taiki-e/install-action@v2.32.17 + uses: taiki-e/install-action@v2.33.12 with: tool: cargo-hack,cargo-ci-cache-clean @@ -88,7 +88,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - name: Install cargo-hack - uses: taiki-e/install-action@v2.32.17 + uses: taiki-e/install-action@v2.33.12 with: tool: cargo-hack @@ -109,7 +109,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - name: Install nextest - uses: taiki-e/install-action@v2.32.17 + uses: taiki-e/install-action@v2.33.12 with: tool: nextest diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2488f7496..b052cebdf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,7 +50,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack and cargo-ci-cache-clean - uses: taiki-e/install-action@v2.32.17 + uses: taiki-e/install-action@v2.33.12 with: tool: cargo-hack,cargo-ci-cache-clean diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index ac5143d58..5698e271c 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.32.17 + uses: taiki-e/install-action@v2.33.12 with: tool: cargo-llvm-cov diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index a10c2411a..fd0b96c7d 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -82,7 +82,7 @@ jobs: toolchain: nightly-2024-04-26 - name: Install cargo-public-api - uses: taiki-e/install-action@v2.32.17 + uses: taiki-e/install-action@v2.33.12 with: tool: cargo-public-api From e4b9d17355d079160416cf8f86a5a87ddbc2e9b2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 May 2024 03:27:31 +0100 Subject: [PATCH 04/63] build(deps): bump codecov/codecov-action from 4.3.0 to 4.3.1 (#3354) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/coverage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 5698e271c..5c228c978 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -31,7 +31,7 @@ jobs: run: cargo llvm-cov --workspace --all-features --codecov --output-path codecov.json - name: Upload coverage to Codecov - uses: codecov/codecov-action@v4.3.0 + uses: codecov/codecov-action@v4.3.1 with: files: codecov.json fail_ci_if_error: true From bb65628de5b01bd0a5fa9552b80b72729340a628 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 May 2024 03:28:35 +0100 Subject: [PATCH 05/63] build(deps): bump taiki-e/install-action from 2.33.12 to 2.33.16 (#3355) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 6 +++--- .github/workflows/ci.yml | 2 +- .github/workflows/coverage.yml | 2 +- .github/workflows/lint.yml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index 10670ab34..9da5de5fd 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -45,7 +45,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack and cargo-ci-cache-clean - uses: taiki-e/install-action@v2.33.12 + uses: taiki-e/install-action@v2.33.16 with: tool: cargo-hack,cargo-ci-cache-clean @@ -88,7 +88,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - name: Install cargo-hack - uses: taiki-e/install-action@v2.33.12 + uses: taiki-e/install-action@v2.33.16 with: tool: cargo-hack @@ -109,7 +109,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - name: Install nextest - uses: taiki-e/install-action@v2.33.12 + uses: taiki-e/install-action@v2.33.16 with: tool: nextest diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b052cebdf..85854bdfd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,7 +50,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack and cargo-ci-cache-clean - uses: taiki-e/install-action@v2.33.12 + uses: taiki-e/install-action@v2.33.16 with: tool: cargo-hack,cargo-ci-cache-clean diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 5c228c978..9ec33ee55 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.33.12 + uses: taiki-e/install-action@v2.33.16 with: tool: cargo-llvm-cov diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index fd0b96c7d..9c6846824 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -82,7 +82,7 @@ jobs: toolchain: nightly-2024-04-26 - name: Install cargo-public-api - uses: taiki-e/install-action@v2.33.12 + uses: taiki-e/install-action@v2.33.16 with: tool: cargo-public-api From c1a638861445cf1aee36d5fd7130ea01b16e3eca Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 6 May 2024 06:03:44 +0100 Subject: [PATCH 06/63] refactor: address clippy warnings --- actix-http/src/h1/dispatcher.rs | 2 +- actix-http/src/h2/dispatcher.rs | 2 +- actix-multipart/src/form/mod.rs | 3 ++- actix-router/src/path.rs | 8 ++------ actix-web/src/config.rs | 2 +- actix-web/src/resource.rs | 2 +- 6 files changed, 8 insertions(+), 11 deletions(-) diff --git a/actix-http/src/h1/dispatcher.rs b/actix-http/src/h1/dispatcher.rs index a24a6bb07..00b51360e 100644 --- a/actix-http/src/h1/dispatcher.rs +++ b/actix-http/src/h1/dispatcher.rs @@ -706,7 +706,7 @@ where req.head_mut().peer_addr = *this.peer_addr; - req.conn_data = this.conn_data.clone(); + req.conn_data.clone_from(this.conn_data); match this.codec.message_type() { // request has no payload diff --git a/actix-http/src/h2/dispatcher.rs b/actix-http/src/h2/dispatcher.rs index 97ceb51e9..400476c88 100644 --- a/actix-http/src/h2/dispatcher.rs +++ b/actix-http/src/h2/dispatcher.rs @@ -126,7 +126,7 @@ where head.headers = parts.headers.into(); head.peer_addr = this.peer_addr; - req.conn_data = this.conn_data.clone(); + req.conn_data.clone_from(&this.conn_data); let fut = this.flow.service.call(req); let config = this.config.clone(); diff --git a/actix-multipart/src/form/mod.rs b/actix-multipart/src/form/mod.rs index 67adfd4b2..451b103fd 100644 --- a/actix-multipart/src/form/mod.rs +++ b/actix-multipart/src/form/mod.rs @@ -313,7 +313,8 @@ where let entry = field_limits .entry(field.name().to_owned()) .or_insert_with(|| T::limit(field.name())); - limits.field_limit_remaining = entry.to_owned(); + + limits.field_limit_remaining.clone_from(entry); T::handle_field(&req, field, &mut limits, &mut state).await?; diff --git a/actix-router/src/path.rs b/actix-router/src/path.rs index 467420cd3..9031ab763 100644 --- a/actix-router/src/path.rs +++ b/actix-router/src/path.rs @@ -154,15 +154,11 @@ impl Path { None } - /// Get matched parameter by name. + /// Returns matched parameter by name. /// /// If keyed parameter is not available empty string is used as default value. pub fn query(&self, key: &str) -> &str { - if let Some(s) = self.get(key) { - s - } else { - "" - } + self.get(key).unwrap_or_default() } /// Return iterator to items in parameter container. diff --git a/actix-web/src/config.rs b/actix-web/src/config.rs index fba0c2717..5e8b056f1 100644 --- a/actix-web/src/config.rs +++ b/actix-web/src/config.rs @@ -148,7 +148,7 @@ impl AppConfig { #[cfg(test)] pub(crate) fn set_host(&mut self, host: &str) { - self.host = host.to_owned(); + host.clone_into(&mut self.host); } } diff --git a/actix-web/src/resource.rs b/actix-web/src/resource.rs index 291d67460..00555b7b2 100644 --- a/actix-web/src/resource.rs +++ b/actix-web/src/resource.rs @@ -771,7 +771,7 @@ mod tests { data3: web::Data| { assert_eq!(**data1, 10); assert_eq!(**data2, '*'); - let error = std::f64::EPSILON; + let error = f64::EPSILON; assert!((**data3 - 1.0).abs() < error); HttpResponse::Ok() }, From 44f502e0503f15f7f03ec3c1e14668bbd9b60b93 Mon Sep 17 00:00:00 2001 From: asonix Date: Mon, 13 May 2024 23:57:58 -0500 Subject: [PATCH 07/63] awc: gate TlsConnectorService behind any feature that uses it (#3350) --- awc/CHANGES.md | 1 + awc/src/client/connector.rs | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/awc/CHANGES.md b/awc/CHANGES.md index 507c8a080..46939a7ca 100644 --- a/awc/CHANGES.md +++ b/awc/CHANGES.md @@ -3,6 +3,7 @@ ## Unreleased - Minimum supported Rust version (MSRV) is now 1.72. +- Fix warning on 1.78 due to unused TlsConnectorService struct ## 3.4.0 diff --git a/awc/src/client/connector.rs b/awc/src/client/connector.rs index 94629b955..b66e13ec7 100644 --- a/awc/src/client/connector.rs +++ b/awc/src/client/connector.rs @@ -649,6 +649,14 @@ where /// service for establish tcp connection and do client tls handshake. /// operation is canceled when timeout limit reached. +#[cfg(any( + feature = "dangerous-h2c", + feature = "openssl", + feature = "rustls-0_20", + feature = "rustls-0_21", + feature = "rustls-0_22-webpki-roots", + feature = "rustls-0_22-native-roots", +))] struct TlsConnectorService { /// TCP connection is canceled on `TcpConnectorInnerService`'s timeout setting. tcp_service: Tcp, @@ -659,6 +667,14 @@ struct TlsConnectorService { timeout: Duration, } +#[cfg(any( + feature = "dangerous-h2c", + feature = "openssl", + feature = "rustls-0_20", + feature = "rustls-0_21", + feature = "rustls-0_22-webpki-roots", + feature = "rustls-0_22-native-roots", +))] impl Service for TlsConnectorService where Tcp: From 3c9a930bd172eba69366c2bf1e5035395c6ebc49 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Tue, 14 May 2024 06:30:58 +0100 Subject: [PATCH 08/63] ci: rely more on justfiles (#3365) --- .cargo/config.toml | 4 --- .github/workflows/ci-post-merge.yml | 36 ++------------------ .github/workflows/ci.yml | 38 ++++++++++----------- Cargo.toml | 2 ++ actix-multipart-derive/Cargo.toml | 9 ++--- actix-web-codegen/Cargo.toml | 9 ++--- justfile | 51 ++++++++++++++++++++++++++--- 7 files changed, 79 insertions(+), 70 deletions(-) diff --git a/.cargo/config.toml b/.cargo/config.toml index 350a924de..6d5a8b810 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -8,7 +8,3 @@ 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" - -# testing -ci-doctest-default = "test --workspace --doc --no-fail-fast -- --nocapture" -ci-doctest = "test --workspace --all-features --doc --no-fail-fast -- --nocapture" diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index 9da5de5fd..d5cb6e620 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -44,10 +44,10 @@ jobs: with: toolchain: ${{ matrix.version.version }} - - name: Install cargo-hack and cargo-ci-cache-clean + - name: Install just, cargo-hack, cargo-nextest, cargo-ci-cache-clean uses: taiki-e/install-action@v2.33.16 with: - tool: cargo-hack,cargo-ci-cache-clean + tool: just,cargo-hack,cargo-nextest,cargo-ci-cache-clean - name: check minimal run: cargo ci-check-min @@ -57,19 +57,7 @@ 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,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 - cargo test --lib --tests -p=actix-test --all-features - cargo test --lib --tests -p=actix-files - cargo test --lib --tests -p=actix-multipart --all-features - cargo test --lib --tests -p=actix-web-actors --all-features + run: just test - name: CI cache clean run: cargo-ci-cache-clean @@ -97,21 +85,3 @@ jobs: - name: check feature combinations run: cargo ci-check-all-feature-powerset-linux - - nextest: - name: nextest - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - name: Install Rust - uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - - - name: Install nextest - uses: taiki-e/install-action@v2.33.16 - with: - tool: nextest - - - name: Test with cargo-nextest - run: cargo nextest run diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 85854bdfd..d7db0be48 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,13 @@ concurrency: cancel-in-progress: true jobs: + read_msrv: + name: Read MSRV + uses: actions-rust-lang/msrv/.github/workflows/msrv.yml@main + build_and_test: + needs: read_msrv + strategy: fail-fast: false matrix: @@ -26,7 +32,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.72.0 } + - { name: msrv, version: "${{ needs.read_msrv.outputs.msrv }}" } - { name: stable, version: stable } name: ${{ matrix.target.name }} / ${{ matrix.version.name }} @@ -49,15 +55,14 @@ jobs: with: toolchain: ${{ matrix.version.version }} - - name: Install cargo-hack and cargo-ci-cache-clean + - name: Install just, cargo-hack, cargo-nextest, cargo-ci-cache-clean uses: taiki-e/install-action@v2.33.16 with: - tool: cargo-hack,cargo-ci-cache-clean + tool: just,cargo-hack,cargo-nextest,cargo-ci-cache-clean - name: workaround MSRV issues if: matrix.version.name == 'msrv' - run: | - cargo update -p=clap --precise=4.4.18 + run: just downgrade-for-msrv - name: check minimal run: cargo ci-check-min @@ -67,20 +72,7 @@ jobs: - name: tests timeout-minutes: 60 - shell: bash - run: | - set -e - cargo test --lib --tests -p=actix-router --no-default-features - 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,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 - cargo test --lib --tests -p=actix-test --all-features - cargo test --lib --tests -p=actix-files - cargo test --lib --tests -p=actix-multipart --all-features - cargo test --lib --tests -p=actix-web-actors --all-features + run: just test - name: CI cache clean run: cargo-ci-cache-clean @@ -112,6 +104,10 @@ jobs: with: toolchain: nightly + - name: Install just + uses: taiki-e/install-action@v2.33.16 + with: + tool: just + - name: doc tests - run: cargo ci-doctest - timeout-minutes: 60 + run: just test-docs diff --git a/Cargo.toml b/Cargo.toml index 9efeda4d1..19d5dd116 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,8 @@ members = [ ] [workspace.package] +homepage = "https://actix.rs" +repository = "https://github.com/actix/actix-web" license = "MIT OR Apache-2.0" edition = "2021" rust-version = "1.72" diff --git a/actix-multipart-derive/Cargo.toml b/actix-multipart-derive/Cargo.toml index 2f049a3fb..e978864a3 100644 --- a/actix-multipart-derive/Cargo.toml +++ b/actix-multipart-derive/Cargo.toml @@ -4,10 +4,11 @@ version = "0.6.1" authors = ["Jacob Halsey "] description = "Multipart form derive macro for Actix Web" keywords = ["http", "web", "framework", "async", "futures"] -homepage = "https://actix.rs" -repository = "https://github.com/actix/actix-web" -license = "MIT OR Apache-2.0" -edition = "2021" +homepage.workspace = true +repository.workspace = true +license.workspace = true +edition.workspace = true +rust-version.workspace = true [package.metadata.docs.rs] rustdoc-args = ["--cfg", "docsrs"] diff --git a/actix-web-codegen/Cargo.toml b/actix-web-codegen/Cargo.toml index 7039ea7df..4a45d4fef 100644 --- a/actix-web-codegen/Cargo.toml +++ b/actix-web-codegen/Cargo.toml @@ -2,14 +2,15 @@ name = "actix-web-codegen" version = "4.2.2" description = "Routing and runtime macros for Actix Web" -homepage = "https://actix.rs" -repository = "https://github.com/actix/actix-web" authors = [ "Nikolay Kim ", "Rob Ede ", ] -license = "MIT OR Apache-2.0" -edition = "2021" +homepage.workspace = true +repository.workspace = true +license.workspace = true +edition.workspace = true +rust-version.workspace = true [lib] proc-macro = true diff --git a/justfile b/justfile index 42979f18c..d92f4bd3d 100644 --- a/justfile +++ b/justfile @@ -6,14 +6,57 @@ fmt: cargo +nightly fmt npx -y prettier --write $(fd --type=file --hidden --extension=md --extension=yml) +# Downgrade dev-dependencies necessary to run MSRV checks/tests. +[private] +downgrade-for-msrv: + cargo update -p=clap --precise=4.4.18 + +msrv := ``` + cargo metadata --format-version=1 \ + | jq -r 'first(.packages[] | select(.source == null and .rust_version)) | .rust_version' \ + | sed -E 's/^1\.([0-9]{2})$/1\.\1\.0/' +``` +msrv_rustup := "+" + msrv + +non_linux_all_features_list := ``` + cargo metadata --format-version=1 \ + | jq '.packages[] | select(.source == null) | .features | keys' \ + | jq -r --slurp \ + --arg exclusions "tokio-uring,io-uring,experimental-io-uring" \ + 'add | unique | . - ($exclusions | split(",")) | join(",")' +``` + +all_crate_features := if os() == "linux" { + "--all-features" +} else { + "--features='" + non_linux_all_features_list + "'" +} + +# Test workspace using MSRV. +test-msrv: downgrade-for-msrv (test msrv_rustup) + +# Test workspace code. +test toolchain="": + cargo {{ toolchain }} test --lib --tests -p=actix-web-codegen --all-features + cargo {{ toolchain }} test --lib --tests -p=actix-multipart-derive --all-features + cargo {{ toolchain }} nextest run -p=actix-router --no-default-features + cargo {{ toolchain }} nextest run --workspace --exclude=actix-web-codegen --exclude=actix-multipart-derive {{ all_crate_features }} --filter-expr="not test(test_reading_deflate_encoding_large_random_rustls)" + +# Test workspace docs. +test-docs toolchain="": && doc + cargo {{ toolchain }} test --doc --workspace {{ all_crate_features }} --no-fail-fast -- --nocapture + +# Test workspace. +test-all toolchain="": (test toolchain) (test-docs toolchain) + # Document crates in workspace. -doc: - RUSTDOCFLAGS="--cfg=docsrs" cargo +nightly doc --no-deps --workspace --features=rustls,openssl +doc *args: + RUSTDOCFLAGS="--cfg=docsrs -Dwarnings" cargo +nightly doc --no-deps --workspace {{ all_crate_features }} {{ args }} # Document crates in workspace and watch for changes. doc-watch: - RUSTDOCFLAGS="--cfg=docsrs" cargo +nightly doc --no-deps --workspace --features=rustls,openssl --open - cargo watch -- RUSTDOCFLAGS="--cfg=docsrs" cargo +nightly doc --no-deps --workspace --features=rustls,openssl + @just doc --open + cargo watch -- just doc # Update READMEs from crate root documentation. update-readmes: && fmt From 33c47c0ba918e87b35de6ba566ef98341672e21a Mon Sep 17 00:00:00 2001 From: asonix Date: Tue, 14 May 2024 00:45:35 -0500 Subject: [PATCH 09/63] Fix type confusion in some scenarios (#3348) * 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 --------- Co-authored-by: Rob Ede --- actix-web/CHANGES.md | 1 + actix-web/src/app_service.rs | 5 +++-- actix-web/src/scope.rs | 5 +++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index c6454ed65..3300a6ffc 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -9,6 +9,7 @@ ### Changed - Minimum supported Rust version (MSRV) is now 1.72. +- Avoid type confusion in rare circumstances ## 4.5.1 diff --git a/actix-web/src/app_service.rs b/actix-web/src/app_service.rs index f2dca954c..65a6ed87b 100644 --- a/actix-web/src/app_service.rs +++ b/actix-web/src/app_service.rs @@ -263,8 +263,9 @@ impl ServiceFactory for AppRoutingFactory { let guards = guards.borrow_mut().take().unwrap_or_default(); let factory_fut = factory.new_service(()); async move { - let service = factory_fut.await?; - Ok((path, guards, service)) + factory_fut + .await + .map(move |service| (path, guards, service)) } })); diff --git a/actix-web/src/scope.rs b/actix-web/src/scope.rs index 27a2827a6..adc9f75d3 100644 --- a/actix-web/src/scope.rs +++ b/actix-web/src/scope.rs @@ -470,8 +470,9 @@ impl ServiceFactory for ScopeFactory { let guards = guards.borrow_mut().take().unwrap_or_default(); let factory_fut = factory.new_service(()); async move { - let service = factory_fut.await?; - Ok((path, guards, service)) + factory_fut + .await + .map(move |service| (path, guards, service)) } })); From c20603fc83ff8d706d9ef3381400e65c17db52e6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 May 2024 05:50:32 +0000 Subject: [PATCH 10/63] build(deps): bump taiki-e/install-action from 2.33.16 to 2.33.22 (#3364) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.33.16 to 2.33.22. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/v2.33.16...v2.33.22) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 4 ++-- .github/workflows/ci.yml | 4 ++-- .github/workflows/coverage.yml | 2 +- .github/workflows/lint.yml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index d5cb6e620..40829d8ef 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -45,7 +45,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install just, cargo-hack, cargo-nextest, cargo-ci-cache-clean - uses: taiki-e/install-action@v2.33.16 + uses: taiki-e/install-action@v2.33.22 with: tool: just,cargo-hack,cargo-nextest,cargo-ci-cache-clean @@ -76,7 +76,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - name: Install cargo-hack - uses: taiki-e/install-action@v2.33.16 + uses: taiki-e/install-action@v2.33.22 with: tool: cargo-hack diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d7db0be48..c1d959fbf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,7 +56,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install just, cargo-hack, cargo-nextest, cargo-ci-cache-clean - uses: taiki-e/install-action@v2.33.16 + uses: taiki-e/install-action@v2.33.22 with: tool: just,cargo-hack,cargo-nextest,cargo-ci-cache-clean @@ -105,7 +105,7 @@ jobs: toolchain: nightly - name: Install just - uses: taiki-e/install-action@v2.33.16 + uses: taiki-e/install-action@v2.33.22 with: tool: just diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 9ec33ee55..943f63223 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.33.16 + uses: taiki-e/install-action@v2.33.22 with: tool: cargo-llvm-cov diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 9c6846824..03b25ecda 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -82,7 +82,7 @@ jobs: toolchain: nightly-2024-04-26 - name: Install cargo-public-api - uses: taiki-e/install-action@v2.33.16 + uses: taiki-e/install-action@v2.33.22 with: tool: cargo-public-api From fff45b28f4219b3c11f40a839649d60ee4e8750e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 May 2024 08:58:05 +0000 Subject: [PATCH 11/63] build(deps): update brotli requirement from 3.3.3 to 6.0.0 (#3353) * build(deps): update brotli requirement from 3.3.3 to 6.0.0 Updates the requirements on [brotli](https://github.com/dropbox/rust-brotli) to permit the latest version. - [Release notes](https://github.com/dropbox/rust-brotli/releases) - [Commits](https://github.com/dropbox/rust-brotli/compare/3.3.3...6.0.0) --- updated-dependencies: - dependency-name: brotli dependency-type: direct:production ... Signed-off-by: dependabot[bot] * docs: update changelogs --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Rob Ede --- actix-http/CHANGES.md | 1 + actix-http/Cargo.toml | 2 +- actix-web/CHANGES.md | 6 +++++- actix-web/Cargo.toml | 2 +- awc/CHANGES.md | 2 +- awc/Cargo.toml | 2 +- 6 files changed, 10 insertions(+), 5 deletions(-) diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index fddd1c2c3..699575068 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -4,6 +4,7 @@ ### Changed +- Update `brotli` dependency to `6`. - Minimum supported Rust version (MSRV) is now 1.72. ## 3.6.0 diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index 38969e901..05de2cb80 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -114,7 +114,7 @@ sha1 = { version = "0.10", optional = true } actix-tls = { version = "3.3", default-features = false, optional = true } # compress-* -brotli = { version = "3.3.3", optional = true } +brotli = { version = "6", optional = true } flate2 = { version = "1.0.13", optional = true } zstd = { version = "0.13", optional = true } diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 3300a6ffc..ea9967693 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -8,8 +8,12 @@ ### Changed +- Update `brotli` dependency to `6`. - Minimum supported Rust version (MSRV) is now 1.72. -- Avoid type confusion in rare circumstances + +### Fixed + +- Avoid type confusion with `rustls` in some circumstances. ## 4.5.1 diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index aea8856b1..b4c713817 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -125,7 +125,7 @@ actix-files = "0.6" actix-test = { version = "0.1", features = ["openssl", "rustls-0_22"] } awc = { version = "3", features = ["openssl"] } -brotli = "3.3.3" +brotli = "6" const-str = "0.5" criterion = { version = "0.5", features = ["html_reports"] } env_logger = "0.11" diff --git a/awc/CHANGES.md b/awc/CHANGES.md index 46939a7ca..9bb787ab6 100644 --- a/awc/CHANGES.md +++ b/awc/CHANGES.md @@ -2,8 +2,8 @@ ## Unreleased +- Update `brotli` dependency to `6`. - Minimum supported Rust version (MSRV) is now 1.72. -- Fix warning on 1.78 due to unused TlsConnectorService struct ## 3.4.0 diff --git a/awc/Cargo.toml b/awc/Cargo.toml index da9e78ae8..aa77b0241 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -116,7 +116,7 @@ actix-tls = { version = "3.3", features = ["openssl", "rustls-0_22"] } actix-utils = "3" actix-web = { version = "4", features = ["openssl"] } -brotli = "3.3.3" +brotli = "6" const-str = "0.5" env_logger = "0.11" flate2 = "1.0.13" From 2d035c066ea60e9113ce9a710728a59ad03a0066 Mon Sep 17 00:00:00 2001 From: asonix Date: Sat, 18 May 2024 13:22:53 -0500 Subject: [PATCH 12/63] 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 40829d8ef..8d509d691 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 c1d959fbf..56333e187 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 699575068..f7b20dd6a 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 05de2cb80..efd20905a 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 47ff061cd..ebb7b8b38 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 55085fd73..fac6b136b 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 64eb39c82..f2f8a0e48 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 d50ffc4e3..636ac3161 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 cb82ced00..f9697c4d5 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 e24387182..a58be93c7 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 08b3a249b..fd2064d56 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 13/63] 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 082520447..f465720f1 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 b7aeddad2..b90db638b 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 14/63] 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 56723bd68..83947b0c2 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 c06a00ca9..d19e951e6 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 15/63] 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 ebb7b8b38..3e273d79c 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 f465720f1..b55a8305c 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 7f48fc2cc..69ce080ad 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 b90db638b..1c3d8ff11 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 ea9967693..5b43a51d0 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 b4c713817..cd09c3054 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 88f0ae9be..f86a74406 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 6592079bf..33b1e1894 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 8fb80216b..60d282351 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 9bb787ab6..4031d2bda 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 aa77b0241..2ba8ada31 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 a54960382..5aae394f8 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 b66e13ec7..fbe50b65c 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 1cc3e8c48..719d25119 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 16/63] 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 ed61556a3..e924de261 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 17/63] 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 efd20905a..c00c2ee04 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 3e273d79c..17303c556 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 fac6b136b..fb86bc5ea 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 cb16a4fec..4dd22b585 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 fd2064d56..3ca0d94c2 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 cd09c3054..bd24ea35f 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 86e0575f3..039c0ffbc 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 60d282351..960cf1e2b 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 2ba8ada31..b1ee62361 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 b3eb97367..a8b7e98c1 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 719d25119..7e832f67d 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 5273c3fff..95d4c15f1 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 18/63] 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 f7b20dd6a..61eeb4beb 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 c00c2ee04..57509defc 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 3881b805d..0ba3fdcac 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 69ce080ad..23dde9cf0 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 bd24ea35f..1faee7a42 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 b1ee62361..f844db210 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 19/63] 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 23dde9cf0..3e96f06e5 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 5b43a51d0..993c7c596 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 1faee7a42..cf4da74f0 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 35e07fc0b..4e7e785a5 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 20/63] 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 3e96f06e5..dddcabec9 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 4031d2bda..54c5e9869 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 f844db210..58986f3e5 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 19236b85a..8e7b42812 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 21/63] 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 57509defc..a999e73c8 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 cf4da74f0..32fcc0609 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 58986f3e5..f51b3904b 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 fbe50b65c..5d0b655a4 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 22/63] 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 6d5a8b810..a2345e184 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 23/63] 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 8aa3c8639..6305b45c3 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 0b02e84b9..56e4bed2f 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 751c307b1..12d1b0146 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 32fcc0609..9f3ab6e5e 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 24/63] 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 56333e187..a81f0e8ed 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: From 4f7b334d8054041296b94cdcedd162017e2869dc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 May 2024 10:27:44 +0100 Subject: [PATCH 25/63] build(deps): bump taiki-e/install-action from 2.33.22 to 2.33.26 (#3376) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.33.22 to 2.33.26. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/v2.33.22...v2.33.26) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 4 ++-- .github/workflows/ci.yml | 4 ++-- .github/workflows/coverage.yml | 2 +- .github/workflows/lint.yml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index 8d509d691..dfb0ca56d 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -49,7 +49,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install just, cargo-hack, cargo-nextest, cargo-ci-cache-clean - uses: taiki-e/install-action@v2.33.22 + uses: taiki-e/install-action@v2.33.26 with: tool: just,cargo-hack,cargo-nextest,cargo-ci-cache-clean @@ -80,7 +80,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - name: Install cargo-hack - uses: taiki-e/install-action@v2.33.22 + uses: taiki-e/install-action@v2.33.26 with: tool: cargo-hack diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a81f0e8ed..153ab78f7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -64,7 +64,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install just, cargo-hack, cargo-nextest, cargo-ci-cache-clean - uses: taiki-e/install-action@v2.33.22 + uses: taiki-e/install-action@v2.33.26 with: tool: just,cargo-hack,cargo-nextest,cargo-ci-cache-clean @@ -113,7 +113,7 @@ jobs: toolchain: nightly - name: Install just - uses: taiki-e/install-action@v2.33.22 + uses: taiki-e/install-action@v2.33.26 with: tool: just diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 943f63223..5eaaae8bf 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.33.22 + uses: taiki-e/install-action@v2.33.26 with: tool: cargo-llvm-cov diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 03b25ecda..39392fabb 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -82,7 +82,7 @@ jobs: toolchain: nightly-2024-04-26 - name: Install cargo-public-api - uses: taiki-e/install-action@v2.33.22 + uses: taiki-e/install-action@v2.33.26 with: tool: cargo-public-api From d4bcdf28f24728edadaa584dfc31eabcb8ca1bdf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 May 2024 10:30:27 +0100 Subject: [PATCH 26/63] build(deps): bump JamesIves/github-pages-deploy-action from 4.6.0 to 4.6.1 (#3375) build(deps): bump JamesIves/github-pages-deploy-action Bumps [JamesIves/github-pages-deploy-action](https://github.com/jamesives/github-pages-deploy-action) from 4.6.0 to 4.6.1. - [Release notes](https://github.com/jamesives/github-pages-deploy-action/releases) - [Commits](https://github.com/jamesives/github-pages-deploy-action/compare/v4.6.0...v4.6.1) --- updated-dependencies: - dependency-name: JamesIves/github-pages-deploy-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/upload-doc.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/upload-doc.yml b/.github/workflows/upload-doc.yml index 6352e44d2..b38a80e5b 100644 --- a/.github/workflows/upload-doc.yml +++ b/.github/workflows/upload-doc.yml @@ -35,7 +35,7 @@ jobs: run: echo '' > target/doc/index.html - name: Deploy to GitHub Pages - uses: JamesIves/github-pages-deploy-action@v4.6.0 + uses: JamesIves/github-pages-deploy-action@v4.6.1 with: folder: target/doc single-commit: true From 1b214bc5f5160f8754f1e3fc77039156d7347793 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 May 2024 10:30:48 +0100 Subject: [PATCH 27/63] build(deps): bump codecov/codecov-action from 4.3.1 to 4.4.0 (#3374) Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 4.3.1 to 4.4.0. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/v4.3.1...v4.4.0) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/coverage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 5eaaae8bf..ce370b105 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -31,7 +31,7 @@ jobs: run: cargo llvm-cov --workspace --all-features --codecov --output-path codecov.json - name: Upload coverage to Codecov - uses: codecov/codecov-action@v4.3.1 + uses: codecov/codecov-action@v4.4.0 with: files: codecov.json fail_ci_if_error: true From cc06fd6a5e6881885961156fc112e31f1ddcb5f4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 May 2024 00:57:59 +0000 Subject: [PATCH 28/63] build(deps): bump codecov/codecov-action from 4.4.0 to 4.4.1 (#3381) Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 4.4.0 to 4.4.1. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/v4.4.0...v4.4.1) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/coverage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index ce370b105..8d9494e3e 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -31,7 +31,7 @@ jobs: run: cargo llvm-cov --workspace --all-features --codecov --output-path codecov.json - name: Upload coverage to Codecov - uses: codecov/codecov-action@v4.4.0 + uses: codecov/codecov-action@v4.4.1 with: files: codecov.json fail_ci_if_error: true From 26efa64278ccb0ec2a0d49f0364c9d7930bb57f5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 May 2024 00:58:18 +0000 Subject: [PATCH 29/63] build(deps): bump taiki-e/install-action from 2.33.26 to 2.33.34 (#3380) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.33.26 to 2.33.34. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/v2.33.26...v2.33.34) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 4 ++-- .github/workflows/ci.yml | 4 ++-- .github/workflows/coverage.yml | 2 +- .github/workflows/lint.yml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index dfb0ca56d..4e4f266b6 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -49,7 +49,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install just, cargo-hack, cargo-nextest, cargo-ci-cache-clean - uses: taiki-e/install-action@v2.33.26 + uses: taiki-e/install-action@v2.33.34 with: tool: just,cargo-hack,cargo-nextest,cargo-ci-cache-clean @@ -80,7 +80,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - name: Install cargo-hack - uses: taiki-e/install-action@v2.33.26 + uses: taiki-e/install-action@v2.33.34 with: tool: cargo-hack diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 153ab78f7..1f7a5d812 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -64,7 +64,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install just, cargo-hack, cargo-nextest, cargo-ci-cache-clean - uses: taiki-e/install-action@v2.33.26 + uses: taiki-e/install-action@v2.33.34 with: tool: just,cargo-hack,cargo-nextest,cargo-ci-cache-clean @@ -113,7 +113,7 @@ jobs: toolchain: nightly - name: Install just - uses: taiki-e/install-action@v2.33.26 + uses: taiki-e/install-action@v2.33.34 with: tool: just diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 8d9494e3e..ff1767fb3 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.33.26 + uses: taiki-e/install-action@v2.33.34 with: tool: cargo-llvm-cov diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 39392fabb..630f0604c 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -82,7 +82,7 @@ jobs: toolchain: nightly-2024-04-26 - name: Install cargo-public-api - uses: taiki-e/install-action@v2.33.26 + uses: taiki-e/install-action@v2.33.34 with: tool: cargo-public-api From 3ce97effa22e4e9ad4dc719d7791b665abf2c9eb Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Tue, 28 May 2024 01:21:23 +0100 Subject: [PATCH 30/63] ci: delete upload doc workflow --- .github/workflows/coverage.yml | 4 ++-- .github/workflows/upload-doc.yml | 41 -------------------------------- 2 files changed, 2 insertions(+), 43 deletions(-) delete mode 100644 .github/workflows/upload-doc.yml diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index ff1767fb3..d3467c698 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -22,10 +22,10 @@ jobs: with: components: llvm-tools-preview - - name: Install cargo-llvm-cov + - name: Install just,cargo-llvm-cov uses: taiki-e/install-action@v2.33.34 with: - tool: cargo-llvm-cov + tool: just,cargo-llvm-cov - name: Generate code coverage run: cargo llvm-cov --workspace --all-features --codecov --output-path codecov.json diff --git a/.github/workflows/upload-doc.yml b/.github/workflows/upload-doc.yml deleted file mode 100644 index b38a80e5b..000000000 --- a/.github/workflows/upload-doc.yml +++ /dev/null @@ -1,41 +0,0 @@ -name: Upload Documentation - -on: - push: - branches: [master] - -permissions: - contents: read - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - build: - permissions: - contents: write - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - name: Install Rust - uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - with: - toolchain: nightly - - - name: Build Docs - run: cargo +nightly doc --no-deps --workspace --all-features - env: - RUSTDOCFLAGS: --cfg=docsrs - - - name: Tweak HTML - run: echo '' > target/doc/index.html - - - name: Deploy to GitHub Pages - uses: JamesIves/github-pages-deploy-action@v4.6.1 - with: - folder: target/doc - single-commit: true From dd84bcb6095aba3b95939a30b7209390ce90f9db Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Jun 2024 02:24:09 +0100 Subject: [PATCH 31/63] build(deps): bump taiki-e/install-action from 2.33.34 to 2.34.0 (#3386) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.33.34 to 2.34.0. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/v2.33.34...v2.34.0) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 4 ++-- .github/workflows/ci.yml | 4 ++-- .github/workflows/coverage.yml | 2 +- .github/workflows/lint.yml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index 4e4f266b6..4231b4dc2 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -49,7 +49,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install just, cargo-hack, cargo-nextest, cargo-ci-cache-clean - uses: taiki-e/install-action@v2.33.34 + uses: taiki-e/install-action@v2.34.0 with: tool: just,cargo-hack,cargo-nextest,cargo-ci-cache-clean @@ -80,7 +80,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - name: Install cargo-hack - uses: taiki-e/install-action@v2.33.34 + uses: taiki-e/install-action@v2.34.0 with: tool: cargo-hack diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1f7a5d812..ed2930bc6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -64,7 +64,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install just, cargo-hack, cargo-nextest, cargo-ci-cache-clean - uses: taiki-e/install-action@v2.33.34 + uses: taiki-e/install-action@v2.34.0 with: tool: just,cargo-hack,cargo-nextest,cargo-ci-cache-clean @@ -113,7 +113,7 @@ jobs: toolchain: nightly - name: Install just - uses: taiki-e/install-action@v2.33.34 + uses: taiki-e/install-action@v2.34.0 with: tool: just diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index d3467c698..da892bd7a 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -23,7 +23,7 @@ jobs: components: llvm-tools-preview - name: Install just,cargo-llvm-cov - uses: taiki-e/install-action@v2.33.34 + uses: taiki-e/install-action@v2.34.0 with: tool: just,cargo-llvm-cov diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 630f0604c..629396986 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -82,7 +82,7 @@ jobs: toolchain: nightly-2024-04-26 - name: Install cargo-public-api - uses: taiki-e/install-action@v2.33.34 + uses: taiki-e/install-action@v2.34.0 with: tool: cargo-public-api From 5c18569b7896f0816b72efa172600a898e596281 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Fri, 7 Jun 2024 14:17:10 +0100 Subject: [PATCH 32/63] docs: align App:app_data arg name --- actix-web/src/app.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/actix-web/src/app.rs b/actix-web/src/app.rs index 1a3b79086..3d86d1f9b 100644 --- a/actix-web/src/app.rs +++ b/actix-web/src/app.rs @@ -112,8 +112,8 @@ where /// }) /// ``` #[doc(alias = "manage")] - pub fn app_data(mut self, ext: U) -> Self { - self.extensions.insert(ext); + pub fn app_data(mut self, data: U) -> Self { + self.extensions.insert(data); self } From ebd8bb266d07828d3556ee10ee8a4c3d9bd0d98e Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Fri, 7 Jun 2024 14:31:17 +0100 Subject: [PATCH 33/63] ci: fix cargo-public-api --- .github/workflows/lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 629396986..d7a16ccb4 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -79,7 +79,7 @@ jobs: - name: Install Rust uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 with: - toolchain: nightly-2024-04-26 + toolchain: nightly-2024-06-07 - name: Install cargo-public-api uses: taiki-e/install-action@v2.34.0 From 85655f731d9d23f9b472b0a2ace817031c8c5e8d Mon Sep 17 00:00:00 2001 From: Abedi Date: Fri, 7 Jun 2024 17:25:29 +0330 Subject: [PATCH 34/63] From Boxed ResponseError impl added (#3388) * From Boxed ResponseError impl added * docs: update changelog --------- Co-authored-by: Rob Ede --- actix-web/CHANGES.md | 4 ++++ actix-web/src/error/error.rs | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 993c7c596..e0390563c 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -2,6 +2,10 @@ ## Unreleased +### Added + +- Implement `From>` for `Error`. + ## 4.6.0 ### Added diff --git a/actix-web/src/error/error.rs b/actix-web/src/error/error.rs index 3a5a128f6..670a58a00 100644 --- a/actix-web/src/error/error.rs +++ b/actix-web/src/error/error.rs @@ -60,6 +60,12 @@ impl From for Error { } } +impl From> for Error { + fn from(value: Box) -> Self { + Error { cause: value } + } +} + impl From for Response { fn from(err: Error) -> Response { err.error_response().into() From b2d0196f342f0f90a9e9e32584f0826bebed4891 Mon Sep 17 00:00:00 2001 From: Dylan Anthony <43723790+dbanty@users.noreply.github.com> Date: Fri, 7 Jun 2024 08:08:13 -0600 Subject: [PATCH 35/63] Do not require actix-router default features from actix-web-codegen (#3372) * fix: Do not require actix-router default features from actix-web-codegen * docs: update changelog * test: update trybuild stderr --------- Co-authored-by: Dylan Anthony Co-authored-by: Rob Ede --- actix-web-codegen/CHANGES.md | 1 + actix-web-codegen/Cargo.toml | 2 +- .../tests/trybuild/route-malformed-path-fail.stderr | 5 +---- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/actix-web-codegen/CHANGES.md b/actix-web-codegen/CHANGES.md index a5acdd21c..875c4021e 100644 --- a/actix-web-codegen/CHANGES.md +++ b/actix-web-codegen/CHANGES.md @@ -2,6 +2,7 @@ ## Unreleased +- Prevent inclusion of default `actix-router` features. - Minimum supported Rust version (MSRV) is now 1.72. ## 4.2.2 diff --git a/actix-web-codegen/Cargo.toml b/actix-web-codegen/Cargo.toml index 4a45d4fef..31c470694 100644 --- a/actix-web-codegen/Cargo.toml +++ b/actix-web-codegen/Cargo.toml @@ -16,7 +16,7 @@ rust-version.workspace = true proc-macro = true [dependencies] -actix-router = "0.5" +actix-router = { version = "0.5", default-features = false } proc-macro2 = "1" quote = "1" syn = { version = "2", features = ["full", "extra-traits"] } diff --git a/actix-web-codegen/tests/trybuild/route-malformed-path-fail.stderr b/actix-web-codegen/tests/trybuild/route-malformed-path-fail.stderr index 93c510109..c1100c784 100644 --- a/actix-web-codegen/tests/trybuild/route-malformed-path-fail.stderr +++ b/actix-web-codegen/tests/trybuild/route-malformed-path-fail.stderr @@ -20,10 +20,7 @@ error: custom attribute panicked 13 | #[get("/{}")] | ^^^^^^^^^^^^^ | - = help: message: Wrong path pattern: "/{}" regex parse error: - ((?s-m)^/(?P<>[^/]+))$ - ^ - error: empty capture group name + = help: message: Wrong path pattern: "/{}" empty capture group names are not allowed error: custom attribute panicked --> $DIR/route-malformed-path-fail.rs:23:1 From 8fdf35895478b2ed5f08651e123922c012ae2937 Mon Sep 17 00:00:00 2001 From: Raphael C Date: Fri, 7 Jun 2024 16:31:53 +0200 Subject: [PATCH 36/63] Add app_data method to GuardContext (#3341) * changes: guard * fix(guard): docs link to app_data * docs: fix changelog --------- Co-authored-by: Rob Ede --- actix-web/CHANGES.md | 1 + actix-web/src/guard/mod.rs | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index e0390563c..757fdce68 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -4,6 +4,7 @@ ### Added +- Add `guard::GuardContext::app_data()` method. - Implement `From>` for `Error`. ## 4.6.0 diff --git a/actix-web/src/guard/mod.rs b/actix-web/src/guard/mod.rs index 9451a60f9..41609953a 100644 --- a/actix-web/src/guard/mod.rs +++ b/actix-web/src/guard/mod.rs @@ -110,6 +110,12 @@ impl<'a> GuardContext<'a> { pub fn header(&self) -> Option { H::parse(self.req).ok() } + + /// Counterpart to [HttpRequest::app_data](crate::HttpRequest::app_data). + #[inline] + pub fn app_data(&self) -> Option<&T> { + self.req.app_data() + } } /// Interface for routing guards. @@ -512,4 +518,18 @@ mod tests { .to_srv_request(); assert!(guard.check(&req.guard_ctx())); } + + #[test] + fn app_data() { + const TEST_VALUE: u32 = 42; + let guard = fn_guard(|ctx| dbg!(ctx.app_data::()) == Some(&TEST_VALUE)); + + let req = TestRequest::default().app_data(TEST_VALUE).to_srv_request(); + assert!(guard.check(&req.guard_ctx())); + + let req = TestRequest::default() + .app_data(TEST_VALUE * 2) + .to_srv_request(); + assert!(!guard.check(&req.guard_ctx())); + } } From 8b4d23a69a0cdf5ac9a32d59ab2b3cbb21b71ffa Mon Sep 17 00:00:00 2001 From: Matt Palmer Date: Sat, 8 Jun 2024 00:40:55 +1000 Subject: [PATCH 37/63] Allow disabling redirect following in actix-test (#3356) If you're testing that redirects are being properly generated, then it's useful to not have the client go off on a wild goose chase of its own. Co-authored-by: Rob Ede --- actix-test/CHANGES.md | 3 ++- actix-test/src/lib.rs | 21 ++++++++++++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/actix-test/CHANGES.md b/actix-test/CHANGES.md index b55a8305c..940b595c0 100644 --- a/actix-test/CHANGES.md +++ b/actix-test/CHANGES.md @@ -3,8 +3,9 @@ ## 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. +- Add `TestServerConfig::disable_redirects()` method. - Various types from `awc`, such as `ClientRequest` and `ClientResponse`, are now re-exported. +- Minimum supported Rust version (MSRV) is now 1.72. ## 0.1.3 diff --git a/actix-test/src/lib.rs b/actix-test/src/lib.rs index 1c3d8ff11..433f14571 100644 --- a/actix-test/src/lib.rs +++ b/actix-test/src/lib.rs @@ -149,6 +149,8 @@ where StreamType::Rustls023(_) => true, }; + let client_cfg = cfg.clone(); + // run server in separate orphaned thread thread::spawn(move || { rt::System::new().block_on(async move { @@ -460,7 +462,13 @@ where } }; - Client::builder().connector(connector).finish() + let mut client_builder = Client::builder().connector(connector); + + if client_cfg.disable_redirects { + client_builder = client_builder.disable_redirects(); + } + + client_builder.finish() }; TestServer { @@ -507,6 +515,7 @@ pub struct TestServerConfig { client_request_timeout: Duration, port: u16, workers: usize, + disable_redirects: bool, } impl Default for TestServerConfig { @@ -524,6 +533,7 @@ impl TestServerConfig { client_request_timeout: Duration::from_secs(5), port: 0, workers: 1, + disable_redirects: false, } } @@ -611,6 +621,15 @@ impl TestServerConfig { self.workers = workers; self } + + /// Instruct the client to not follow redirects. + /// + /// By default, the client will follow up to 10 consecutive redirects + /// before giving up. + pub fn disable_redirects(mut self) -> Self { + self.disable_redirects = true; + self + } } /// A basic HTTP server controller that simplifies the process of writing integration tests for From 4493aa35d006c8a479db2b1410802461655eba25 Mon Sep 17 00:00:00 2001 From: asonix Date: Fri, 7 Jun 2024 09:41:32 -0500 Subject: [PATCH 38/63] actix-http::ws: Remove redundant + 4 byte reservation when masked (#3371) * actix-http::ws: Remove redundant + 4 byte reservation when masked * actix-http: Update CHANGES wrt byte fix * docs: remove changelog entry --------- Co-authored-by: Rob Ede --- actix-http/src/ws/frame.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/actix-http/src/ws/frame.rs b/actix-http/src/ws/frame.rs index c9fb0cde9..35b3f8e66 100644 --- a/actix-http/src/ws/frame.rs +++ b/actix-http/src/ws/frame.rs @@ -178,14 +178,14 @@ impl Parser { }; if payload_len < 126 { - dst.reserve(p_len + 2 + if mask { 4 } else { 0 }); + dst.reserve(p_len + 2); dst.put_slice(&[one, two | payload_len as u8]); } else if payload_len <= 65_535 { - dst.reserve(p_len + 4 + if mask { 4 } else { 0 }); + dst.reserve(p_len + 4); dst.put_slice(&[one, two | 126]); dst.put_u16(payload_len as u16); } else { - dst.reserve(p_len + 10 + if mask { 4 } else { 0 }); + dst.reserve(p_len + 10); dst.put_slice(&[one, two | 127]); dst.put_u64(payload_len as u64); }; From 5221c1b19452cd98fa03882374295b56fa9af327 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Fri, 7 Jun 2024 14:51:05 +0100 Subject: [PATCH 39/63] ci: pin msrv lookup job --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ed2930bc6..ab611fc0a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,7 @@ concurrency: jobs: read_msrv: name: Read MSRV - uses: actions-rust-lang/msrv/.github/workflows/msrv.yml@main + uses: actions-rust-lang/msrv/.github/workflows/msrv.yml@v0.1.0 build_and_test: needs: read_msrv From b9305ff59db29f6ce20740ef2ad5db3e4b60ffe5 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Fri, 7 Jun 2024 16:04:04 +0100 Subject: [PATCH 40/63] chore: fmt --- actix-multipart/README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/actix-multipart/README.md b/actix-multipart/README.md index 83947b0c2..35c7f9a1f 100644 --- a/actix-multipart/README.md +++ b/actix-multipart/README.md @@ -15,7 +15,6 @@ - ## Example Dependencies: @@ -65,6 +64,7 @@ async fn main() -> std::io::Result<()> { ``` Curl request : + ```bash curl -v --request POST \ --url http://localhost:8080/videos \ @@ -72,7 +72,6 @@ curl -v --request POST \ -F file=@./Cargo.lock ``` - ### Examples -https://github.com/actix/examples/tree/master/forms/multipart \ No newline at end of file +https://github.com/actix/examples/tree/master/forms/multipart From cff958e5187b4980d8a87c2a886a284ccbd3d9b2 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Fri, 7 Jun 2024 16:10:25 +0100 Subject: [PATCH 41/63] chore: address clippy lint --- actix-test/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/actix-test/src/lib.rs b/actix-test/src/lib.rs index 433f14571..48d5079a7 100644 --- a/actix-test/src/lib.rs +++ b/actix-test/src/lib.rs @@ -488,6 +488,7 @@ enum HttpVer { Both, } +#[allow(clippy::large_enum_variant)] #[derive(Clone)] enum StreamType { Tcp, From 534cfe1fda1d65b9cea7d75a0a8c55f46439bb4e Mon Sep 17 00:00:00 2001 From: Sebastian Detert Date: Fri, 7 Jun 2024 17:22:48 +0200 Subject: [PATCH 42/63] feat: add .customize().add_cookie() (#3215) * feat: add .customize().add_cookie() * docs: added cookie hint * fix: added unwrap to test of add_cookie() * docs: added changelog entry for .customize().add_cookie() * chore: make append_header infallible * docs: update changelog --------- Co-authored-by: Rob Ede --- actix-web/CHANGES.md | 1 + actix-web/src/response/customize_responder.rs | 42 ++++++++++++++++++- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 757fdce68..75f3631c9 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -4,6 +4,7 @@ ### Added +- Add `CustomizeResponder::add_cookie()` method. - Add `guard::GuardContext::app_data()` method. - Implement `From>` for `Error`. diff --git a/actix-web/src/response/customize_responder.rs b/actix-web/src/response/customize_responder.rs index 4cbd96e20..6a43ac5e6 100644 --- a/actix-web/src/response/customize_responder.rs +++ b/actix-web/src/response/customize_responder.rs @@ -7,7 +7,7 @@ use actix_http::{ use crate::{HttpRequest, HttpResponse, Responder}; -/// Allows overriding status code and headers for a [`Responder`]. +/// Allows overriding status code and headers (including cookies) for a [`Responder`]. /// /// Created by calling the [`customize`](Responder::customize) method on a [`Responder`] type. pub struct CustomizeResponder { @@ -137,6 +137,29 @@ impl CustomizeResponder { Some(&mut self.inner) } } + + /// Appends a `cookie` to the final response. + /// + /// # Errors + /// + /// Final response will be an error if `cookie` cannot be converted into a valid header value. + #[cfg(feature = "cookies")] + pub fn add_cookie(mut self, cookie: &crate::cookie::Cookie<'_>) -> Self { + use actix_http::header::{TryIntoHeaderValue as _, SET_COOKIE}; + + if let Some(inner) = self.inner() { + match cookie.to_string().try_into_value() { + Ok(val) => { + inner.append_headers.append(SET_COOKIE, val); + } + Err(err) => { + self.error = Some(err.into()); + } + } + } + + self + } } impl Responder for CustomizeResponder @@ -175,6 +198,7 @@ mod tests { use super::*; use crate::{ + cookie::Cookie, http::header::{HeaderValue, CONTENT_TYPE}, test::TestRequest, }; @@ -209,6 +233,22 @@ mod tests { to_bytes(res.into_body()).await.unwrap(), Bytes::from_static(b"test"), ); + + let res = "test" + .to_string() + .customize() + .add_cookie(&Cookie::new("name", "value")) + .respond_to(&req); + + assert!(res.status().is_success()); + assert_eq!( + res.cookies().collect::>>(), + vec![Cookie::new("name", "value")], + ); + assert_eq!( + to_bytes(res.into_body()).await.unwrap(), + Bytes::from_static(b"test"), + ); } #[actix_rt::test] From c366649516dcd1d780ca8b7938397dac61338c15 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Fri, 7 Jun 2024 16:57:03 +0100 Subject: [PATCH 43/63] docs: example of CPU core pinning --- actix-web/Cargo.toml | 2 +- actix-web/examples/worker-cpu-pin.rs | 41 ++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 actix-web/examples/worker-cpu-pin.rs diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index 9f3ab6e5e..a666f14be 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -35,7 +35,6 @@ features = [ "secure-cookies", ] - [lib] name = "actix_web" path = "src/lib.rs" @@ -130,6 +129,7 @@ awc = { version = "3", features = ["openssl"] } brotli = "6" const-str = "0.5" +core_affinity = "0.8" criterion = { version = "0.5", features = ["html_reports"] } env_logger = "0.11" flate2 = "1.0.13" diff --git a/actix-web/examples/worker-cpu-pin.rs b/actix-web/examples/worker-cpu-pin.rs new file mode 100644 index 000000000..58e060821 --- /dev/null +++ b/actix-web/examples/worker-cpu-pin.rs @@ -0,0 +1,41 @@ +use std::{ + io, + sync::{ + atomic::{AtomicUsize, Ordering}, + Arc, + }, + thread, +}; + +use actix_web::{middleware, web, App, HttpServer}; + +async fn hello() -> &'static str { + "Hello world!" +} + +#[actix_web::main] +async fn main() -> io::Result<()> { + env_logger::init_from_env(env_logger::Env::new().default_filter_or("info")); + + let core_ids = core_affinity::get_core_ids().unwrap(); + let n_core_ids = core_ids.len(); + let next_core_id = Arc::new(AtomicUsize::new(0)); + + HttpServer::new(move || { + let pin = Arc::clone(&next_core_id).fetch_add(1, Ordering::AcqRel); + log::info!( + "setting CPU affinity for worker {}: pinning to core {}", + thread::current().name().unwrap(), + pin, + ); + core_affinity::set_for_current(core_ids[pin]); + + App::new() + .wrap(middleware::Logger::default()) + .service(web::resource("/").get(hello)) + }) + .bind(("127.0.0.1", 8080))? + .workers(n_core_ids) + .run() + .await +} From 3db7891303093d5992cfd3483405b80b495b8f8e Mon Sep 17 00:00:00 2001 From: Jonathan Lim Date: Fri, 7 Jun 2024 15:10:48 -0700 Subject: [PATCH 44/63] Scope macro (#3136) * add scope proc macro * Update scope macro code to work with current HttpServiceFactory * started some test code * add some unit tests * code formatting cleanup * add another test for combining and calling 2 scopes * format code with formatter * Update actix-web-codegen/src/lib.rs with comment documentation fix Co-authored-by: oliver <151407407+kwfn@users.noreply.github.com> * work in progress. revised procedural macro to change othe macro call * add tests again. refactor nested code. * clean up code. fix bugs with route and method attributes with parameters * clean up for rust fmt * clean up for rust fmt * fix out of date comment for scope macro * sync to master branch by adding test_wrap * needed to format code * test: split out scope tests * test: add negative tests * chore: move imports back inside (?) * docs: tweak scope docs * fix: prevent trailing slashes in scope prefixes * chore: address clippy lints --------- Co-authored-by: oliver <151407407+kwfn@users.noreply.github.com> Co-authored-by: Rob Ede --- actix-web-codegen/CHANGES.md | 1 + actix-web-codegen/src/lib.rs | 50 +++++ actix-web-codegen/src/route.rs | 20 +- actix-web-codegen/src/scope.rs | 103 +++++++++ .../tests/{test_macro.rs => routes.rs} | 0 actix-web-codegen/tests/scopes.rs | 200 ++++++++++++++++++ actix-web-codegen/tests/trybuild.rs | 5 + .../tests/trybuild/scope-invalid-args.rs | 14 ++ .../tests/trybuild/scope-invalid-args.stderr | 17 ++ .../tests/trybuild/scope-missing-args.rs | 6 + .../tests/trybuild/scope-missing-args.stderr | 7 + .../tests/trybuild/scope-on-handler.rs | 8 + .../tests/trybuild/scope-on-handler.stderr | 5 + .../tests/trybuild/scope-trailing-slash.rs | 6 + .../trybuild/scope-trailing-slash.stderr | 5 + actix-web/src/lib.rs | 1 + awc/src/client/connector.rs | 2 +- justfile | 6 +- 18 files changed, 439 insertions(+), 17 deletions(-) create mode 100644 actix-web-codegen/src/scope.rs rename actix-web-codegen/tests/{test_macro.rs => routes.rs} (100%) create mode 100644 actix-web-codegen/tests/scopes.rs create mode 100644 actix-web-codegen/tests/trybuild/scope-invalid-args.rs create mode 100644 actix-web-codegen/tests/trybuild/scope-invalid-args.stderr create mode 100644 actix-web-codegen/tests/trybuild/scope-missing-args.rs create mode 100644 actix-web-codegen/tests/trybuild/scope-missing-args.stderr create mode 100644 actix-web-codegen/tests/trybuild/scope-on-handler.rs create mode 100644 actix-web-codegen/tests/trybuild/scope-on-handler.stderr create mode 100644 actix-web-codegen/tests/trybuild/scope-trailing-slash.rs create mode 100644 actix-web-codegen/tests/trybuild/scope-trailing-slash.stderr diff --git a/actix-web-codegen/CHANGES.md b/actix-web-codegen/CHANGES.md index 875c4021e..792f6aa4f 100644 --- a/actix-web-codegen/CHANGES.md +++ b/actix-web-codegen/CHANGES.md @@ -2,6 +2,7 @@ ## Unreleased +- Add `#[scope]` macro. - Prevent inclusion of default `actix-router` features. - Minimum supported Rust version (MSRV) is now 1.72. diff --git a/actix-web-codegen/src/lib.rs b/actix-web-codegen/src/lib.rs index 6d6c9ab5c..c518007a0 100644 --- a/actix-web-codegen/src/lib.rs +++ b/actix-web-codegen/src/lib.rs @@ -83,6 +83,7 @@ use proc_macro::TokenStream; use quote::quote; mod route; +mod scope; /// Creates resource handler, allowing multiple HTTP method guards. /// @@ -197,6 +198,43 @@ method_macro!(Options, options); method_macro!(Trace, trace); method_macro!(Patch, patch); +/// Prepends a path prefix to all handlers using routing macros inside the attached module. +/// +/// # Syntax +/// +/// ``` +/// # use actix_web_codegen::scope; +/// #[scope("/prefix")] +/// mod api { +/// // ... +/// } +/// ``` +/// +/// # Arguments +/// +/// - `"/prefix"` - Raw literal string to be prefixed onto contained handlers' paths. +/// +/// # Example +/// +/// ``` +/// # use actix_web_codegen::{scope, get}; +/// # use actix_web::Responder; +/// #[scope("/api")] +/// mod api { +/// # use super::*; +/// #[get("/hello")] +/// pub async fn hello() -> impl Responder { +/// // this has path /api/hello +/// "Hello, world!" +/// } +/// } +/// # fn main() {} +/// ``` +#[proc_macro_attribute] +pub fn scope(args: TokenStream, input: TokenStream) -> TokenStream { + scope::with_scope(args, input) +} + /// Marks async main function as the Actix Web system entry-point. /// /// Note that Actix Web also works under `#[tokio::main]` since version 4.0. However, this macro is @@ -240,3 +278,15 @@ pub fn test(_: TokenStream, item: TokenStream) -> TokenStream { output.extend(item); output } + +/// Converts the error to a token stream and appends it to the original input. +/// +/// Returning the original input in addition to the error is good for IDEs which can gracefully +/// recover and show more precise errors within the macro body. +/// +/// See for more info. +fn input_and_compile_error(mut item: TokenStream, err: syn::Error) -> TokenStream { + let compile_err = TokenStream::from(err.to_compile_error()); + item.extend(compile_err); + item +} diff --git a/actix-web-codegen/src/route.rs b/actix-web-codegen/src/route.rs index 7a2dfc051..d0605fc04 100644 --- a/actix-web-codegen/src/route.rs +++ b/actix-web-codegen/src/route.rs @@ -6,10 +6,12 @@ use proc_macro2::{Span, TokenStream as TokenStream2}; use quote::{quote, ToTokens, TokenStreamExt}; use syn::{punctuated::Punctuated, Ident, LitStr, Path, Token}; +use crate::input_and_compile_error; + #[derive(Debug)] pub struct RouteArgs { - path: syn::LitStr, - options: Punctuated, + pub(crate) path: syn::LitStr, + pub(crate) options: Punctuated, } impl syn::parse::Parse for RouteArgs { @@ -78,7 +80,7 @@ macro_rules! standard_method_type { } } - fn from_path(method: &Path) -> Result { + pub(crate) fn from_path(method: &Path) -> Result { match () { $(_ if method.is_ident(stringify!($lower)) => Ok(Self::$variant),)+ _ => Err(()), @@ -542,15 +544,3 @@ pub(crate) fn with_methods(input: TokenStream) -> TokenStream { Err(err) => input_and_compile_error(input, err), } } - -/// Converts the error to a token stream and appends it to the original input. -/// -/// Returning the original input in addition to the error is good for IDEs which can gracefully -/// recover and show more precise errors within the macro body. -/// -/// See for more info. -fn input_and_compile_error(mut item: TokenStream, err: syn::Error) -> TokenStream { - let compile_err = TokenStream::from(err.to_compile_error()); - item.extend(compile_err); - item -} diff --git a/actix-web-codegen/src/scope.rs b/actix-web-codegen/src/scope.rs new file mode 100644 index 000000000..067d95a60 --- /dev/null +++ b/actix-web-codegen/src/scope.rs @@ -0,0 +1,103 @@ +use proc_macro::TokenStream; +use proc_macro2::{Span, TokenStream as TokenStream2}; +use quote::{quote, ToTokens as _}; + +use crate::{ + input_and_compile_error, + route::{MethodType, RouteArgs}, +}; + +pub fn with_scope(args: TokenStream, input: TokenStream) -> TokenStream { + match with_scope_inner(args, input.clone()) { + Ok(stream) => stream, + Err(err) => input_and_compile_error(input, err), + } +} + +fn with_scope_inner(args: TokenStream, input: TokenStream) -> syn::Result { + if args.is_empty() { + return Err(syn::Error::new( + Span::call_site(), + "missing arguments for scope macro, expected: #[scope(\"/prefix\")]", + )); + } + + let scope_prefix = syn::parse::(args.clone()).map_err(|err| { + syn::Error::new( + err.span(), + "argument to scope macro is not a string literal, expected: #[scope(\"/prefix\")]", + ) + })?; + + let scope_prefix_value = scope_prefix.value(); + + if scope_prefix_value.ends_with('/') { + // trailing slashes cause non-obvious problems + // it's better to point them out to developers rather than + + return Err(syn::Error::new( + scope_prefix.span(), + "scopes should not have trailing slashes; see https://docs.rs/actix-web/4/actix_web/struct.Scope.html#avoid-trailing-slashes", + )); + } + + let mut module = syn::parse::(input).map_err(|err| { + syn::Error::new(err.span(), "#[scope] macro must be attached to a module") + })?; + + // modify any routing macros (method or route[s]) attached to + // functions by prefixing them with this scope macro's argument + if let Some((_, items)) = &mut module.content { + for item in items { + if let syn::Item::Fn(fun) = item { + fun.attrs = fun + .attrs + .iter() + .map(|attr| modify_attribute_with_scope(attr, &scope_prefix_value)) + .collect(); + } + } + } + + Ok(module.to_token_stream().into()) +} + +/// Checks if the attribute is a method type and has a route path, then modifies it. +fn modify_attribute_with_scope(attr: &syn::Attribute, scope_path: &str) -> syn::Attribute { + match (attr.parse_args::(), attr.clone().meta) { + (Ok(route_args), syn::Meta::List(meta_list)) if has_allowed_methods_in_scope(attr) => { + let modified_path = format!("{}{}", scope_path, route_args.path.value()); + + let options_tokens: Vec = route_args + .options + .iter() + .map(|option| { + quote! { ,#option } + }) + .collect(); + + let combined_options_tokens: TokenStream2 = + options_tokens + .into_iter() + .fold(TokenStream2::new(), |mut acc, ts| { + acc.extend(std::iter::once(ts)); + acc + }); + + syn::Attribute { + meta: syn::Meta::List(syn::MetaList { + tokens: quote! { #modified_path #combined_options_tokens }, + ..meta_list.clone() + }), + ..attr.clone() + } + } + _ => attr.clone(), + } +} + +fn has_allowed_methods_in_scope(attr: &syn::Attribute) -> bool { + MethodType::from_path(attr.path()).is_ok() + || attr.path().is_ident("route") + || attr.path().is_ident("ROUTE") +} diff --git a/actix-web-codegen/tests/test_macro.rs b/actix-web-codegen/tests/routes.rs similarity index 100% rename from actix-web-codegen/tests/test_macro.rs rename to actix-web-codegen/tests/routes.rs diff --git a/actix-web-codegen/tests/scopes.rs b/actix-web-codegen/tests/scopes.rs new file mode 100644 index 000000000..6a370a2e2 --- /dev/null +++ b/actix-web-codegen/tests/scopes.rs @@ -0,0 +1,200 @@ +use actix_web::{guard::GuardContext, http, http::header, web, App, HttpResponse, Responder}; +use actix_web_codegen::{delete, get, post, route, routes, scope}; + +pub fn image_guard(ctx: &GuardContext) -> bool { + ctx.header::() + .map(|h| h.preference() == "image/*") + .unwrap_or(false) +} + +#[scope("/test")] +mod scope_module { + // ensure that imports can be brought into the scope + use super::*; + + #[get("/test/guard", guard = "image_guard")] + pub async fn guard() -> impl Responder { + HttpResponse::Ok() + } + + #[get("/test")] + pub async fn test() -> impl Responder { + HttpResponse::Ok().finish() + } + + #[get("/twice-test/{value}")] + pub async fn twice(value: web::Path) -> impl actix_web::Responder { + let int_value: i32 = value.parse().unwrap_or(0); + let doubled = int_value * 2; + HttpResponse::Ok().body(format!("Twice value: {}", doubled)) + } + + #[post("/test")] + pub async fn post() -> impl Responder { + HttpResponse::Ok().body("post works") + } + + #[delete("/test")] + pub async fn delete() -> impl Responder { + "delete works" + } + + #[route("/test", method = "PUT", method = "PATCH", method = "CUSTOM")] + pub async fn multiple_shared_path() -> impl Responder { + HttpResponse::Ok().finish() + } + + #[routes] + #[head("/test1")] + #[connect("/test2")] + #[options("/test3")] + #[trace("/test4")] + async fn multiple_separate_paths() -> impl Responder { + HttpResponse::Ok().finish() + } + + // test calling this from other mod scope with scope attribute... + pub fn mod_common(message: String) -> impl actix_web::Responder { + HttpResponse::Ok().body(message) + } +} + +/// Scope doc string to check in cargo expand. +#[scope("/v1")] +mod mod_scope_v1 { + use super::*; + + /// Route doc string to check in cargo expand. + #[get("/test")] + pub async fn test() -> impl Responder { + scope_module::mod_common("version1 works".to_string()) + } +} + +#[scope("/v2")] +mod mod_scope_v2 { + use super::*; + + // check to make sure non-function tokens in the scope block are preserved... + enum TestEnum { + Works, + } + + #[get("/test")] + pub async fn test() -> impl Responder { + // make sure this type still exists... + let test_enum = TestEnum::Works; + + match test_enum { + TestEnum::Works => scope_module::mod_common("version2 works".to_string()), + } + } +} + +#[actix_rt::test] +async fn scope_get_async() { + let srv = actix_test::start(|| App::new().service(scope_module::test)); + + let request = srv.request(http::Method::GET, srv.url("/test/test")); + let response = request.send().await.unwrap(); + assert!(response.status().is_success()); +} + +#[actix_rt::test] +async fn scope_get_param_async() { + let srv = actix_test::start(|| App::new().service(scope_module::twice)); + + let request = srv.request(http::Method::GET, srv.url("/test/twice-test/4")); + let mut response = request.send().await.unwrap(); + let body = response.body().await.unwrap(); + let body_str = String::from_utf8(body.to_vec()).unwrap(); + assert_eq!(body_str, "Twice value: 8"); +} + +#[actix_rt::test] +async fn scope_post_async() { + let srv = actix_test::start(|| App::new().service(scope_module::post)); + + let request = srv.request(http::Method::POST, srv.url("/test/test")); + let mut response = request.send().await.unwrap(); + let body = response.body().await.unwrap(); + let body_str = String::from_utf8(body.to_vec()).unwrap(); + assert_eq!(body_str, "post works"); +} + +#[actix_rt::test] +async fn multiple_shared_path_async() { + let srv = actix_test::start(|| App::new().service(scope_module::multiple_shared_path)); + + let request = srv.request(http::Method::PUT, srv.url("/test/test")); + let response = request.send().await.unwrap(); + assert!(response.status().is_success()); + + let request = srv.request(http::Method::PATCH, srv.url("/test/test")); + let response = request.send().await.unwrap(); + assert!(response.status().is_success()); +} + +#[actix_rt::test] +async fn multiple_multi_path_async() { + let srv = actix_test::start(|| App::new().service(scope_module::multiple_separate_paths)); + + let request = srv.request(http::Method::HEAD, srv.url("/test/test1")); + let response = request.send().await.unwrap(); + assert!(response.status().is_success()); + + let request = srv.request(http::Method::CONNECT, srv.url("/test/test2")); + let response = request.send().await.unwrap(); + assert!(response.status().is_success()); + + let request = srv.request(http::Method::OPTIONS, srv.url("/test/test3")); + let response = request.send().await.unwrap(); + assert!(response.status().is_success()); + + let request = srv.request(http::Method::TRACE, srv.url("/test/test4")); + let response = request.send().await.unwrap(); + assert!(response.status().is_success()); +} + +#[actix_rt::test] +async fn scope_delete_async() { + let srv = actix_test::start(|| App::new().service(scope_module::delete)); + + let request = srv.request(http::Method::DELETE, srv.url("/test/test")); + let mut response = request.send().await.unwrap(); + let body = response.body().await.unwrap(); + let body_str = String::from_utf8(body.to_vec()).unwrap(); + assert_eq!(body_str, "delete works"); +} + +#[actix_rt::test] +async fn scope_get_with_guard_async() { + let srv = actix_test::start(|| App::new().service(scope_module::guard)); + + let request = srv + .request(http::Method::GET, srv.url("/test/test/guard")) + .insert_header(("Accept", "image/*")); + let response = request.send().await.unwrap(); + assert!(response.status().is_success()); +} + +#[actix_rt::test] +async fn scope_v1_v2_async() { + let srv = actix_test::start(|| { + App::new() + .service(mod_scope_v1::test) + .service(mod_scope_v2::test) + }); + + let request = srv.request(http::Method::GET, srv.url("/v1/test")); + let mut response = request.send().await.unwrap(); + let body = response.body().await.unwrap(); + let body_str = String::from_utf8(body.to_vec()).unwrap(); + assert_eq!(body_str, "version1 works"); + + let request = srv.request(http::Method::GET, srv.url("/v2/test")); + let mut response = request.send().await.unwrap(); + let body = response.body().await.unwrap(); + let body_str = String::from_utf8(body.to_vec()).unwrap(); + assert_eq!(body_str, "version2 works"); +} diff --git a/actix-web-codegen/tests/trybuild.rs b/actix-web-codegen/tests/trybuild.rs index 88f77548b..91073cf3b 100644 --- a/actix-web-codegen/tests/trybuild.rs +++ b/actix-web-codegen/tests/trybuild.rs @@ -18,6 +18,11 @@ fn compile_macros() { t.compile_fail("tests/trybuild/routes-missing-method-fail.rs"); t.compile_fail("tests/trybuild/routes-missing-args-fail.rs"); + t.compile_fail("tests/trybuild/scope-on-handler.rs"); + t.compile_fail("tests/trybuild/scope-missing-args.rs"); + t.compile_fail("tests/trybuild/scope-invalid-args.rs"); + t.compile_fail("tests/trybuild/scope-trailing-slash.rs"); + t.pass("tests/trybuild/docstring-ok.rs"); t.pass("tests/trybuild/test-runtime.rs"); diff --git a/actix-web-codegen/tests/trybuild/scope-invalid-args.rs b/actix-web-codegen/tests/trybuild/scope-invalid-args.rs new file mode 100644 index 000000000..ec021d5eb --- /dev/null +++ b/actix-web-codegen/tests/trybuild/scope-invalid-args.rs @@ -0,0 +1,14 @@ +use actix_web_codegen::scope; + +const PATH: &str = "/api"; + +#[scope(PATH)] +mod api_const {} + +#[scope(true)] +mod api_bool {} + +#[scope(123)] +mod api_num {} + +fn main() {} diff --git a/actix-web-codegen/tests/trybuild/scope-invalid-args.stderr b/actix-web-codegen/tests/trybuild/scope-invalid-args.stderr new file mode 100644 index 000000000..0ab335966 --- /dev/null +++ b/actix-web-codegen/tests/trybuild/scope-invalid-args.stderr @@ -0,0 +1,17 @@ +error: argument to scope macro is not a string literal, expected: #[scope("/prefix")] + --> tests/trybuild/scope-invalid-args.rs:5:9 + | +5 | #[scope(PATH)] + | ^^^^ + +error: argument to scope macro is not a string literal, expected: #[scope("/prefix")] + --> tests/trybuild/scope-invalid-args.rs:8:9 + | +8 | #[scope(true)] + | ^^^^ + +error: argument to scope macro is not a string literal, expected: #[scope("/prefix")] + --> tests/trybuild/scope-invalid-args.rs:11:9 + | +11 | #[scope(123)] + | ^^^ diff --git a/actix-web-codegen/tests/trybuild/scope-missing-args.rs b/actix-web-codegen/tests/trybuild/scope-missing-args.rs new file mode 100644 index 000000000..39bcb9d1a --- /dev/null +++ b/actix-web-codegen/tests/trybuild/scope-missing-args.rs @@ -0,0 +1,6 @@ +use actix_web_codegen::scope; + +#[scope] +mod api {} + +fn main() {} diff --git a/actix-web-codegen/tests/trybuild/scope-missing-args.stderr b/actix-web-codegen/tests/trybuild/scope-missing-args.stderr new file mode 100644 index 000000000..d59842e39 --- /dev/null +++ b/actix-web-codegen/tests/trybuild/scope-missing-args.stderr @@ -0,0 +1,7 @@ +error: missing arguments for scope macro, expected: #[scope("/prefix")] + --> tests/trybuild/scope-missing-args.rs:3:1 + | +3 | #[scope] + | ^^^^^^^^ + | + = note: this error originates in the attribute macro `scope` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/actix-web-codegen/tests/trybuild/scope-on-handler.rs b/actix-web-codegen/tests/trybuild/scope-on-handler.rs new file mode 100644 index 000000000..e5d478981 --- /dev/null +++ b/actix-web-codegen/tests/trybuild/scope-on-handler.rs @@ -0,0 +1,8 @@ +use actix_web_codegen::scope; + +#[scope("/api")] +async fn index() -> &'static str { + "Hello World!" +} + +fn main() {} diff --git a/actix-web-codegen/tests/trybuild/scope-on-handler.stderr b/actix-web-codegen/tests/trybuild/scope-on-handler.stderr new file mode 100644 index 000000000..4491f42dd --- /dev/null +++ b/actix-web-codegen/tests/trybuild/scope-on-handler.stderr @@ -0,0 +1,5 @@ +error: #[scope] macro must be attached to a module + --> tests/trybuild/scope-on-handler.rs:4:1 + | +4 | async fn index() -> &'static str { + | ^^^^^ diff --git a/actix-web-codegen/tests/trybuild/scope-trailing-slash.rs b/actix-web-codegen/tests/trybuild/scope-trailing-slash.rs new file mode 100644 index 000000000..84632b59f --- /dev/null +++ b/actix-web-codegen/tests/trybuild/scope-trailing-slash.rs @@ -0,0 +1,6 @@ +use actix_web_codegen::scope; + +#[scope("/api/")] +mod api {} + +fn main() {} diff --git a/actix-web-codegen/tests/trybuild/scope-trailing-slash.stderr b/actix-web-codegen/tests/trybuild/scope-trailing-slash.stderr new file mode 100644 index 000000000..66933432e --- /dev/null +++ b/actix-web-codegen/tests/trybuild/scope-trailing-slash.stderr @@ -0,0 +1,5 @@ +error: scopes should not have trailing slashes; see https://docs.rs/actix-web/4/actix_web/struct.Scope.html#avoid-trailing-slashes + --> tests/trybuild/scope-trailing-slash.rs:3:9 + | +3 | #[scope("/api/")] + | ^^^^^^^ diff --git a/actix-web/src/lib.rs b/actix-web/src/lib.rs index f86a74406..205391388 100644 --- a/actix-web/src/lib.rs +++ b/actix-web/src/lib.rs @@ -145,5 +145,6 @@ codegen_reexport!(delete); codegen_reexport!(trace); codegen_reexport!(connect); codegen_reexport!(options); +codegen_reexport!(scope); pub(crate) type BoxError = Box; diff --git a/awc/src/client/connector.rs b/awc/src/client/connector.rs index 5d0b655a4..f3d443070 100644 --- a/awc/src/client/connector.rs +++ b/awc/src/client/connector.rs @@ -1080,7 +1080,7 @@ mod resolver { // resolver struct is cached in thread local so new clients can reuse the existing instance thread_local! { - static TRUST_DNS_RESOLVER: RefCell> = RefCell::new(None); + static TRUST_DNS_RESOLVER: RefCell> = const { RefCell::new(None) }; } // get from thread local or construct a new trust-dns resolver. diff --git a/justfile b/justfile index d92f4bd3d..4e106ef11 100644 --- a/justfile +++ b/justfile @@ -4,7 +4,7 @@ _list: # Format workspace. fmt: cargo +nightly fmt - npx -y prettier --write $(fd --type=file --hidden --extension=md --extension=yml) + fd --hidden --type=file --extension=md --extension=yml --exec-batch npx -y prettier --write # Downgrade dev-dependencies necessary to run MSRV checks/tests. [private] @@ -32,6 +32,10 @@ all_crate_features := if os() == "linux" { "--features='" + non_linux_all_features_list + "'" } +# Run Clippy over workspace. +clippy toolchain="": + cargo {{ toolchain }} clippy --workspace --all-targets {{ all_crate_features }} + # Test workspace using MSRV. test-msrv: downgrade-for-msrv (test msrv_rustup) From 7c4c26d2df5d344ae524a72f733fd3af0c13a3a2 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sat, 8 Jun 2024 05:26:26 +0100 Subject: [PATCH 45/63] feat: expose Identity middleware (#3390) --- .github/workflows/lint.yml | 2 +- actix-web/CHANGES.md | 1 + actix-web/src/middleware/compat.rs | 13 ++---------- actix-web/src/middleware/condition.rs | 4 ++-- .../src/middleware/{noop.rs => identity.rs} | 20 +++++++++++-------- actix-web/src/middleware/mod.rs | 16 ++++++--------- 6 files changed, 24 insertions(+), 32 deletions(-) rename actix-web/src/middleware/{noop.rs => identity.rs} (57%) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index d7a16ccb4..dd44d4cb3 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -89,5 +89,5 @@ jobs: - name: Generate API diff run: | for f in $(find -mindepth 2 -maxdepth 2 -name Cargo.toml); do - cargo public-api --manifest-path "$f" diff ${{ github.event.pull_request.base.sha }}..${{ github.sha }} + cargo public-api --manifest-path "$f" --simplified diff ${{ github.event.pull_request.base.sha }}..${{ github.sha }} done diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 75f3631c9..93fbbf465 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -4,6 +4,7 @@ ### Added +- Add `middleware::Identity` type. - Add `CustomizeResponder::add_cookie()` method. - Add `guard::GuardContext::app_data()` method. - Implement `From>` for `Error`. diff --git a/actix-web/src/middleware/compat.rs b/actix-web/src/middleware/compat.rs index 7df510a5c..963dfdabb 100644 --- a/actix-web/src/middleware/compat.rs +++ b/actix-web/src/middleware/compat.rs @@ -38,15 +38,6 @@ pub struct Compat { transform: T, } -#[cfg(test)] -impl Compat { - pub(crate) fn noop() -> Self { - Self { - transform: super::Noop, - } - } -} - impl Compat { /// Wrap a middleware to give it broader compatibility. pub fn new(middleware: T) -> Self { @@ -152,7 +143,7 @@ mod tests { use crate::{ dev::ServiceRequest, http::StatusCode, - middleware::{self, Condition, Logger}, + middleware::{self, Condition, Identity, Logger}, test::{self, call_service, init_service, TestRequest}, web, App, HttpResponse, }; @@ -225,7 +216,7 @@ mod tests { async fn compat_noop_is_noop() { let srv = test::ok_service(); - let mw = Compat::noop() + let mw = Compat::new(Identity) .new_transform(srv.into_service()) .await .unwrap(); diff --git a/actix-web/src/middleware/condition.rs b/actix-web/src/middleware/condition.rs index 55c56d494..5ee4467d9 100644 --- a/actix-web/src/middleware/condition.rs +++ b/actix-web/src/middleware/condition.rs @@ -141,7 +141,7 @@ mod tests { header::{HeaderValue, CONTENT_TYPE}, StatusCode, }, - middleware::{self, ErrorHandlerResponse, ErrorHandlers}, + middleware::{self, ErrorHandlerResponse, ErrorHandlers, Identity}, test::{self, TestRequest}, web::Bytes, HttpResponse, @@ -158,7 +158,7 @@ mod tests { #[test] fn compat_with_builtin_middleware() { - let _ = Condition::new(true, middleware::Compat::noop()); + let _ = Condition::new(true, middleware::Compat::new(Identity)); let _ = Condition::new(true, middleware::Logger::default()); let _ = Condition::new(true, middleware::Compress::default()); let _ = Condition::new(true, middleware::NormalizePath::trim()); diff --git a/actix-web/src/middleware/noop.rs b/actix-web/src/middleware/identity.rs similarity index 57% rename from actix-web/src/middleware/noop.rs rename to actix-web/src/middleware/identity.rs index ae7da1d81..de374a57b 100644 --- a/actix-web/src/middleware/noop.rs +++ b/actix-web/src/middleware/identity.rs @@ -2,35 +2,39 @@ use actix_utils::future::{ready, Ready}; -use crate::dev::{Service, Transform}; +use crate::dev::{forward_ready, Service, Transform}; /// A no-op middleware that passes through request and response untouched. -pub(crate) struct Noop; +#[derive(Debug, Clone, Default)] +#[non_exhaustive] +pub struct Identity; -impl, Req> Transform for Noop { +impl, Req> Transform for Identity { type Response = S::Response; type Error = S::Error; - type Transform = NoopService; + type Transform = IdentityMiddleware; type InitError = (); type Future = Ready>; + #[inline] fn new_transform(&self, service: S) -> Self::Future { - ready(Ok(NoopService { service })) + ready(Ok(IdentityMiddleware { service })) } } #[doc(hidden)] -pub(crate) struct NoopService { +pub struct IdentityMiddleware { service: S, } -impl, Req> Service for NoopService { +impl, Req> Service for IdentityMiddleware { type Response = S::Response; type Error = S::Error; type Future = S::Future; - crate::dev::forward_ready!(service); + forward_ready!(service); + #[inline] fn call(&self, req: Req) -> Self::Future { self.service.call(req) } diff --git a/actix-web/src/middleware/mod.rs b/actix-web/src/middleware/mod.rs index e924de261..1c27b1110 100644 --- a/actix-web/src/middleware/mod.rs +++ b/actix-web/src/middleware/mod.rs @@ -218,31 +218,27 @@ //! [lab_from_fn]: https://docs.rs/actix-web-lab/latest/actix_web_lab/middleware/fn.from_fn.html mod compat; +#[cfg(feature = "__compress")] +mod compress; mod condition; mod default_headers; mod err_handlers; +mod identity; mod logger; -#[cfg(test)] -mod noop; mod normalize; -#[cfg(test)] -pub(crate) use self::noop::Noop; +#[cfg(feature = "__compress")] +pub use self::compress::Compress; pub use self::{ compat::Compat, condition::Condition, default_headers::DefaultHeaders, err_handlers::{ErrorHandlerResponse, ErrorHandlers}, + identity::Identity, logger::Logger, normalize::{NormalizePath, TrailingSlash}, }; -#[cfg(feature = "__compress")] -mod compress; - -#[cfg(feature = "__compress")] -pub use self::compress::Compress; - #[cfg(test)] mod tests { use super::*; From ebc43dcf1b52ddf083090402b28392469ffa1997 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 9 Jun 2024 00:10:15 +0100 Subject: [PATCH 46/63] feat: forwards-compatibility for handler visibility inheritance fix (#3391) --- actix-web-codegen/CHANGES.md | 1 + actix-web-codegen/Cargo.toml | 4 ++++ actix-web-codegen/src/route.rs | 9 ++++++++- actix-web-codegen/tests/scopes.rs | 2 +- actix-web/CHANGES.md | 2 ++ actix-web/Cargo.toml | 26 ++++++++++++++++++++++---- awc/Cargo.toml | 2 +- 7 files changed, 39 insertions(+), 7 deletions(-) diff --git a/actix-web-codegen/CHANGES.md b/actix-web-codegen/CHANGES.md index 792f6aa4f..0a240680e 100644 --- a/actix-web-codegen/CHANGES.md +++ b/actix-web-codegen/CHANGES.md @@ -3,6 +3,7 @@ ## Unreleased - Add `#[scope]` macro. +- Add `compat-routing-macros-force-pub` crate feature which, on-by-default, which when disabled causes handlers to inherit their attached function's visibility. - Prevent inclusion of default `actix-router` features. - Minimum supported Rust version (MSRV) is now 1.72. diff --git a/actix-web-codegen/Cargo.toml b/actix-web-codegen/Cargo.toml index 31c470694..7eb995039 100644 --- a/actix-web-codegen/Cargo.toml +++ b/actix-web-codegen/Cargo.toml @@ -15,6 +15,10 @@ rust-version.workspace = true [lib] proc-macro = true +[features] +default = ["compat-routing-macros-force-pub"] +compat-routing-macros-force-pub = [] + [dependencies] actix-router = { version = "0.5", default-features = false } proc-macro2 = "1" diff --git a/actix-web-codegen/src/route.rs b/actix-web-codegen/src/route.rs index d0605fc04..e24903e3a 100644 --- a/actix-web-codegen/src/route.rs +++ b/actix-web-codegen/src/route.rs @@ -413,6 +413,13 @@ impl ToTokens for Route { doc_attributes, } = self; + #[allow(unused_variables)] // used when force-pub feature is disabled + let vis = &ast.vis; + + // TODO(breaking): remove this force-pub forwards-compatibility feature + #[cfg(feature = "compat-routing-macros-force-pub")] + let vis = syn::Visibility::Public(::default()); + let registrations: TokenStream2 = args .iter() .map(|args| { @@ -460,7 +467,7 @@ impl ToTokens for Route { let stream = quote! { #(#doc_attributes)* #[allow(non_camel_case_types, missing_docs)] - pub struct #name; + #vis struct #name; impl ::actix_web::dev::HttpServiceFactory for #name { fn register(self, __config: &mut actix_web::dev::AppService) { diff --git a/actix-web-codegen/tests/scopes.rs b/actix-web-codegen/tests/scopes.rs index 6a370a2e2..4ee6db16f 100644 --- a/actix-web-codegen/tests/scopes.rs +++ b/actix-web-codegen/tests/scopes.rs @@ -49,7 +49,7 @@ mod scope_module { #[connect("/test2")] #[options("/test3")] #[trace("/test4")] - async fn multiple_separate_paths() -> impl Responder { + pub async fn multiple_separate_paths() -> impl Responder { HttpResponse::Ok().finish() } diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 93fbbf465..97bdf29c2 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -7,6 +7,8 @@ - Add `middleware::Identity` type. - Add `CustomizeResponder::add_cookie()` method. - Add `guard::GuardContext::app_data()` method. +- Add `compat-routing-macros-force-pub` crate feature which (on-by-default) which, when disabled, causes handlers to inherit their attached function's visibility. +- Add `compat` crate feature group (on-by-default) which, when disabled, helps with transitioning to some planned v5.0 breaking changes, starting only with `compat-routing-macros-force-pub`. - Implement `From>` for `Error`. ## 4.6.0 diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index a666f14be..c36f317ce 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -40,7 +40,16 @@ name = "actix_web" path = "src/lib.rs" [features] -default = ["macros", "compress-brotli", "compress-gzip", "compress-zstd", "cookies", "http2", "unicode"] +default = [ + "macros", + "compress-brotli", + "compress-gzip", + "compress-zstd", + "cookies", + "http2", + "unicode", + "compat", +] # Brotli algorithm content-encoding support compress-brotli = ["actix-http/compress-brotli", "__compress"] @@ -50,14 +59,15 @@ compress-gzip = ["actix-http/compress-gzip", "__compress"] compress-zstd = ["actix-http/compress-zstd", "__compress"] # Routing and runtime proc macros -macros = ["actix-macros", "actix-web-codegen"] +macros = ["dep:actix-macros", "dep:actix-web-codegen"] # Cookies support -cookies = ["cookie"] +cookies = ["dep:cookie"] # Secure & signed cookies secure-cookies = ["cookies", "cookie/secure"] +# HTTP/2 support (including h2c). http2 = ["actix-http/http2"] # TLS via OpenSSL @@ -84,6 +94,14 @@ __compress = [] # io-uring feature only available for Linux OSes. experimental-io-uring = ["actix-server/io-uring"] +# Feature group which, when disabled, helps migrate code to v5.0. +compat = [ + "compat-routing-macros-force-pub", +] + +# Opt-out forwards-compatibility for handler visibility inheritance fix. +compat-routing-macros-force-pub = ["actix-web-codegen?/compat-routing-macros-force-pub"] + [dependencies] actix-codec = "0.5" actix-macros = { version = "0.2.3", optional = true } @@ -95,7 +113,7 @@ actix-tls = { version = "3.4", default-features = false, optional = true } actix-http = { version = "3.7", features = ["ws"] } actix-router = { version = "0.5.3", default-features = false, features = ["http"] } -actix-web-codegen = { version = "4.2", optional = true } +actix-web-codegen = { version = "4.2", optional = true, default-features = false } ahash = "0.8" bytes = "1" diff --git a/awc/Cargo.toml b/awc/Cargo.toml index f51b3904b..09f580aff 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -64,7 +64,7 @@ compress-gzip = ["actix-http/compress-gzip", "__compress"] compress-zstd = ["actix-http/compress-zstd", "__compress"] # Cookie parsing and cookie jar -cookies = ["cookie"] +cookies = ["dep:cookie"] # Use `trust-dns-resolver` crate as DNS resolver trust-dns = ["trust-dns-resolver"] From d6f885127d5d72096b9129085508b9af29c5cfee Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 9 Jun 2024 00:16:36 +0100 Subject: [PATCH 47/63] chore(actix-test): prepare release 0.1.4 --- actix-test/CHANGES.md | 2 ++ actix-test/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/actix-test/CHANGES.md b/actix-test/CHANGES.md index 940b595c0..8088c2504 100644 --- a/actix-test/CHANGES.md +++ b/actix-test/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +## 0.1.4 + - Add `TestServerConfig::rustls_0_23()` method for Rustls v0.23 support behind new `rustls-0_23` crate feature. - Add `TestServerConfig::disable_redirects()` method. - 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 dddcabec9..1ae619145 100644 --- a/actix-test/Cargo.toml +++ b/actix-test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-test" -version = "0.1.3" +version = "0.1.4" authors = [ "Nikolay Kim ", "Rob Ede ", From b4faf8820cb14a3648bb03385e0ceca844de8d9d Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 9 Jun 2024 00:19:09 +0100 Subject: [PATCH 48/63] chore(actix-web-codegen): prepare release 4.3.0 --- actix-web-codegen/CHANGES.md | 2 ++ actix-web-codegen/Cargo.toml | 2 +- actix-web-codegen/README.md | 4 ++-- actix-web/Cargo.toml | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/actix-web-codegen/CHANGES.md b/actix-web-codegen/CHANGES.md index 0a240680e..d143723f4 100644 --- a/actix-web-codegen/CHANGES.md +++ b/actix-web-codegen/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.3.0 + - Add `#[scope]` macro. - Add `compat-routing-macros-force-pub` crate feature which, on-by-default, which when disabled causes handlers to inherit their attached function's visibility. - Prevent inclusion of default `actix-router` features. diff --git a/actix-web-codegen/Cargo.toml b/actix-web-codegen/Cargo.toml index 7eb995039..7500807d2 100644 --- a/actix-web-codegen/Cargo.toml +++ b/actix-web-codegen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-web-codegen" -version = "4.2.2" +version = "4.3.0" description = "Routing and runtime macros for Actix Web" authors = [ "Nikolay Kim ", diff --git a/actix-web-codegen/README.md b/actix-web-codegen/README.md index 9229f8f16..e61bf5c74 100644 --- a/actix-web-codegen/README.md +++ b/actix-web-codegen/README.md @@ -5,11 +5,11 @@ [![crates.io](https://img.shields.io/crates/v/actix-web-codegen?label=latest)](https://crates.io/crates/actix-web-codegen) -[![Documentation](https://docs.rs/actix-web-codegen/badge.svg?version=4.2.2)](https://docs.rs/actix-web-codegen/4.2.2) +[![Documentation](https://docs.rs/actix-web-codegen/badge.svg?version=4.3.0)](https://docs.rs/actix-web-codegen/4.3.0) ![Version](https://img.shields.io/badge/rustc-1.72+-ab6000.svg) ![License](https://img.shields.io/crates/l/actix-web-codegen.svg)
-[![dependency status](https://deps.rs/crate/actix-web-codegen/4.2.2/status.svg)](https://deps.rs/crate/actix-web-codegen/4.2.2) +[![dependency status](https://deps.rs/crate/actix-web-codegen/4.3.0/status.svg)](https://deps.rs/crate/actix-web-codegen/4.3.0) [![Download](https://img.shields.io/crates/d/actix-web-codegen.svg)](https://crates.io/crates/actix-web-codegen) [![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 c36f317ce..243b91d29 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -113,7 +113,7 @@ actix-tls = { version = "3.4", default-features = false, optional = true } actix-http = { version = "3.7", features = ["ws"] } actix-router = { version = "0.5.3", default-features = false, features = ["http"] } -actix-web-codegen = { version = "4.2", optional = true, default-features = false } +actix-web-codegen = { version = "4.3", optional = true, default-features = false } ahash = "0.8" bytes = "1" From 12a0521ef88d13120363edeca484e75c98af8934 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 9 Jun 2024 00:20:36 +0100 Subject: [PATCH 49/63] chore(actix-multipart): prepare release 0.6.2 --- actix-multipart/CHANGES.md | 2 ++ actix-multipart/Cargo.toml | 2 +- actix-multipart/README.md | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/actix-multipart/CHANGES.md b/actix-multipart/CHANGES.md index 196d2ca93..a91edf9c8 100644 --- a/actix-multipart/CHANGES.md +++ b/actix-multipart/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +## 0.6.2 + - Add testing utilities under new module `test`. - Minimum supported Rust version (MSRV) is now 1.72. diff --git a/actix-multipart/Cargo.toml b/actix-multipart/Cargo.toml index 6e36c3391..f1289d3a2 100644 --- a/actix-multipart/Cargo.toml +++ b/actix-multipart/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-multipart" -version = "0.6.1" +version = "0.6.2" authors = [ "Nikolay Kim ", "Jacob Halsey ", diff --git a/actix-multipart/README.md b/actix-multipart/README.md index 35c7f9a1f..c7697785a 100644 --- a/actix-multipart/README.md +++ b/actix-multipart/README.md @@ -5,11 +5,11 @@ [![crates.io](https://img.shields.io/crates/v/actix-multipart?label=latest)](https://crates.io/crates/actix-multipart) -[![Documentation](https://docs.rs/actix-multipart/badge.svg?version=0.6.1)](https://docs.rs/actix-multipart/0.6.1) +[![Documentation](https://docs.rs/actix-multipart/badge.svg?version=0.6.2)](https://docs.rs/actix-multipart/0.6.2) ![Version](https://img.shields.io/badge/rustc-1.72+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-multipart.svg)
-[![dependency status](https://deps.rs/crate/actix-multipart/0.6.1/status.svg)](https://deps.rs/crate/actix-multipart/0.6.1) +[![dependency status](https://deps.rs/crate/actix-multipart/0.6.2/status.svg)](https://deps.rs/crate/actix-multipart/0.6.2) [![Download](https://img.shields.io/crates/d/actix-multipart.svg)](https://crates.io/crates/actix-multipart) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) From a5c78483f9d83d3f916d75c8a5ce46909faf32bc Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 9 Jun 2024 00:22:03 +0100 Subject: [PATCH 50/63] chore(actix-web): prepare release 4.7.0 --- actix-web/CHANGES.md | 2 ++ actix-web/Cargo.toml | 2 +- actix-web/README.md | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 97bdf29c2..27259dc5c 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.7.0 + ### Added - Add `middleware::Identity` type. diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index 243b91d29..10a507680 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-web" -version = "4.6.0" +version = "4.7.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 4e7e785a5..8b4375bdd 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.6.0)](https://docs.rs/actix-web/4.6.0) +[![Documentation](https://docs.rs/actix-web/badge.svg?version=4.7.0)](https://docs.rs/actix-web/4.7.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.6.0/status.svg)](https://deps.rs/crate/actix-web/4.6.0) +[![Dependency Status](https://deps.rs/crate/actix-web/4.7.0/status.svg)](https://deps.rs/crate/actix-web/4.7.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 40e1034566febd583ea7669e4fa76908e9bfe3ad Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 9 Jun 2024 00:38:49 +0100 Subject: [PATCH 51/63] docs: update changelog --- actix-web/CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 27259dc5c..4e74e0902 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -6,6 +6,7 @@ ### Added +- Add `#[scope]` macro. - Add `middleware::Identity` type. - Add `CustomizeResponder::add_cookie()` method. - Add `guard::GuardContext::app_data()` method. From 266834cf7c0e7b243b671b0b2ac41a20f8100286 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 9 Jun 2024 04:51:53 +0100 Subject: [PATCH 52/63] chore: narrow h2 version --- actix-http/Cargo.toml | 2 +- awc/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index a999e73c8..87e2b391d 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -106,7 +106,7 @@ tokio-util = { version = "0.7", features = ["io", "codec"] } tracing = { version = "0.1.30", default-features = false, features = ["log"] } # http2 -h2 = { version = "0.3.24", optional = true } +h2 = { version = "0.3.26", optional = true } # websockets local-channel = { version = "0.1", optional = true } diff --git a/awc/Cargo.toml b/awc/Cargo.toml index 09f580aff..6ab408ea6 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -92,7 +92,7 @@ cfg-if = "1" derive_more = "0.99.5" futures-core = { version = "0.3.17", default-features = false, features = ["alloc"] } futures-util = { version = "0.3.17", default-features = false, features = ["alloc", "sink"] } -h2 = "0.3.24" +h2 = "0.3.26" http = "0.2.7" itoa = "1" log =" 0.4" From 8018983a68742570d86bd8f5a0ba0b8ed389e75d Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 9 Jun 2024 06:08:21 +0100 Subject: [PATCH 53/63] docs: update changelog for #3393 --- actix-http/CHANGES.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index 61eeb4beb..85ba03100 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -2,6 +2,10 @@ ## Unreleased +### Added + +- Add `error::InvalidStatusCode` re-export. + ## 3.7.0 ### Added From f7646bcc485f43ff4ba987cd613891883a081a07 Mon Sep 17 00:00:00 2001 From: asonix Date: Sun, 9 Jun 2024 00:04:42 -0500 Subject: [PATCH 54/63] actix-web-actors: take the internal buffer when yielding (#3369) * actix-web-actors: take the internal buffer when yielding * actix-web-actors: Add CHANGES entry re: taking buffer --- actix-web-actors/CHANGES.md | 1 + actix-web-actors/src/ws.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/actix-web-actors/CHANGES.md b/actix-web-actors/CHANGES.md index 9a622d8da..3e854c0b8 100644 --- a/actix-web-actors/CHANGES.md +++ b/actix-web-actors/CHANGES.md @@ -2,6 +2,7 @@ ## Unreleased +- Take the encoded buffer when yielding bytes in the response stream rather than splitting the buffer, reducing memory use - Minimum supported Rust version (MSRV) is now 1.72. ## 4.3.0 diff --git a/actix-web-actors/src/ws.rs b/actix-web-actors/src/ws.rs index 1fb903225..7f7607fa9 100644 --- a/actix-web-actors/src/ws.rs +++ b/actix-web-actors/src/ws.rs @@ -710,7 +710,7 @@ where } if !this.buf.is_empty() { - Poll::Ready(Some(Ok(this.buf.split().freeze()))) + Poll::Ready(Some(Ok(std::mem::take(&mut this.buf).freeze()))) } else if this.fut.alive() && !this.closed { Poll::Pending } else { From 22593a1532be29374100de0d256b493f2557bcd3 Mon Sep 17 00:00:00 2001 From: Samuel Marks <807580+SamuelMarks@users.noreply.github.com> Date: Sun, 9 Jun 2024 01:07:56 -0400 Subject: [PATCH 55/63] Re-export `http::status::InvalidStatusCode` (#3393) * [actix-http/src/lib.rs] Expose/re-export `http::status::InvalidStatusCode` * [actix-http/src/error.rs] Re-export `http::status::InvalidStatusCode` ; [actix-http/src/lib.rs] Revert --- actix-http/src/error.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actix-http/src/error.rs b/actix-http/src/error.rs index 69e2f14a1..6f332118e 100644 --- a/actix-http/src/error.rs +++ b/actix-http/src/error.rs @@ -3,7 +3,7 @@ use std::{error::Error as StdError, fmt, io, str::Utf8Error, string::FromUtf8Error}; use derive_more::{Display, Error, From}; -pub use http::Error as HttpError; +pub use http::{status::InvalidStatusCode, Error as HttpError}; use http::{uri::InvalidUri, StatusCode}; use crate::{body::BoxBody, Response}; From 8b8eb4eae1212796216a53aa9ca445108206d7fe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 9 Jun 2024 18:37:42 +0100 Subject: [PATCH 56/63] build(deps): update tokio-uring requirement from 0.4 to 0.5 (#3385) * build(deps): update tokio-uring requirement from 0.4 to 0.5 Updates the requirements on [tokio-uring](https://github.com/tokio-rs/tokio-uring) to permit the latest version. - [Release notes](https://github.com/tokio-rs/tokio-uring/releases) - [Changelog](https://github.com/tokio-rs/tokio-uring/blob/master/CHANGELOG.md) - [Commits](https://github.com/tokio-rs/tokio-uring/compare/v0.4.0...v0.5.0) --- updated-dependencies: - dependency-name: tokio-uring dependency-type: direct:production ... Signed-off-by: dependabot[bot] * chore: narrow actix-server requirement --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Rob Ede --- actix-files/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/actix-files/Cargo.toml b/actix-files/Cargo.toml index 3d82f8a76..a69af3020 100644 --- a/actix-files/Cargo.toml +++ b/actix-files/Cargo.toml @@ -40,8 +40,8 @@ v_htmlescape = "0.15.5" # experimental-io-uring [target.'cfg(target_os = "linux")'.dependencies] -tokio-uring = { version = "0.4", optional = true, features = ["bytes"] } -actix-server = { version = "2.2", optional = true } # ensure matching tokio-uring versions +tokio-uring = { version = "0.5", optional = true, features = ["bytes"] } +actix-server = { version = "2.4", optional = true } # ensure matching tokio-uring versions [dev-dependencies] actix-rt = "2.7" From 37577dcb89c01834820e95d2361eed32732447a5 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 9 Jun 2024 19:45:14 +0100 Subject: [PATCH 57/63] chore(actix-files): prepare release 0.6.6 --- actix-files/CHANGES.md | 3 +++ actix-files/Cargo.toml | 2 +- actix-files/README.md | 4 ++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/actix-files/CHANGES.md b/actix-files/CHANGES.md index 393e7b61a..e94f43907 100644 --- a/actix-files/CHANGES.md +++ b/actix-files/CHANGES.md @@ -2,6 +2,9 @@ ## Unreleased +## 0.6.6 + +- Update `tokio-uring` dependency to `0.4`. - Minimum supported Rust version (MSRV) is now 1.72. ## 0.6.5 diff --git a/actix-files/Cargo.toml b/actix-files/Cargo.toml index a69af3020..7adb8eaf5 100644 --- a/actix-files/Cargo.toml +++ b/actix-files/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-files" -version = "0.6.5" +version = "0.6.6" authors = [ "Nikolay Kim ", "Rob Ede ", diff --git a/actix-files/README.md b/actix-files/README.md index a6b3f63c6..f6d5143f5 100644 --- a/actix-files/README.md +++ b/actix-files/README.md @@ -3,11 +3,11 @@ [![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) +[![Documentation](https://docs.rs/actix-files/badge.svg?version=0.6.6)](https://docs.rs/actix-files/0.6.6) ![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) +[![dependency status](https://deps.rs/crate/actix-files/0.6.6/status.svg)](https://deps.rs/crate/actix-files/0.6.6) [![Download](https://img.shields.io/crates/d/actix-files.svg)](https://crates.io/crates/actix-files) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) From 758ae1dac1c5cc574698f058b30bd075bac8b681 Mon Sep 17 00:00:00 2001 From: Matt Palmer Date: Mon, 10 Jun 2024 05:07:08 +1000 Subject: [PATCH 58/63] actix-test: allow the configuration of the TestServer address (#3351) * actix-test: allow the configuration of the TestServer address This is useful if you're running (say) Selenium tests against a running TestServer, and the Selenium workers are Docker containers elsewhere in the network. Not a *particularly* common use case, perhaps, but one that I can attest happens every now and then. * Update CHANGES.md * Adjust default listen address to avoid test failures --------- Co-authored-by: Rob Ede --- actix-test/CHANGES.md | 2 ++ actix-test/src/lib.rs | 16 +++++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/actix-test/CHANGES.md b/actix-test/CHANGES.md index 8088c2504..dd409c917 100644 --- a/actix-test/CHANGES.md +++ b/actix-test/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +- Add `TestServerConfig::listen_address()` method. + ## 0.1.4 - Add `TestServerConfig::rustls_0_23()` method for Rustls v0.23 support behind new `rustls-0_23` crate feature. diff --git a/actix-test/src/lib.rs b/actix-test/src/lib.rs index 48d5079a7..803320607 100644 --- a/actix-test/src/lib.rs +++ b/actix-test/src/lib.rs @@ -154,7 +154,7 @@ where // run server in separate orphaned thread thread::spawn(move || { rt::System::new().block_on(async move { - let tcp = net::TcpListener::bind(("127.0.0.1", cfg.port)).unwrap(); + let tcp = net::TcpListener::bind((cfg.listen_address.clone(), cfg.port)).unwrap(); let local_addr = tcp.local_addr().unwrap(); let factory = factory.clone(); let srv_cfg = cfg.clone(); @@ -514,6 +514,7 @@ pub struct TestServerConfig { tp: HttpVer, stream: StreamType, client_request_timeout: Duration, + listen_address: String, port: u16, workers: usize, disable_redirects: bool, @@ -532,6 +533,7 @@ impl TestServerConfig { tp: HttpVer::Both, stream: StreamType::Tcp, client_request_timeout: Duration::from_secs(5), + listen_address: "127.0.0.1".to_string(), port: 0, workers: 1, disable_redirects: false, @@ -607,6 +609,14 @@ impl TestServerConfig { self } + /// Sets the address the server will listen on. + /// + /// By default, only listens on `127.0.0.1`. + pub fn listen_address(mut self, addr: impl Into) -> Self { + self.listen_address = addr.into(); + self + } + /// Sets test server port. /// /// By default, a random free port is determined by the OS. @@ -657,9 +667,9 @@ impl TestServer { let scheme = if self.tls { "https" } else { "http" }; if uri.starts_with('/') { - format!("{}://localhost:{}{}", scheme, self.addr.port(), uri) + format!("{}://{}{}", scheme, self.addr, uri) } else { - format!("{}://localhost:{}/{}", scheme, self.addr.port(), uri) + format!("{}://{}/{}", scheme, self.addr, uri) } } From da56de45564640dba4461d5c5f8b5d1f23f25533 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 10 Jun 2024 00:01:17 +0100 Subject: [PATCH 59/63] chore(actix-test): prepare release 0.1.5 --- actix-test/CHANGES.md | 2 ++ actix-test/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/actix-test/CHANGES.md b/actix-test/CHANGES.md index dd409c917..ec2dd6776 100644 --- a/actix-test/CHANGES.md +++ b/actix-test/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +## 0.1.5 + - Add `TestServerConfig::listen_address()` method. ## 0.1.4 diff --git a/actix-test/Cargo.toml b/actix-test/Cargo.toml index 1ae619145..41267c969 100644 --- a/actix-test/Cargo.toml +++ b/actix-test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-test" -version = "0.1.4" +version = "0.1.5" authors = [ "Nikolay Kim ", "Rob Ede ", From a2b9823d9d428b2abec75e98afb8dfd412098886 Mon Sep 17 00:00:00 2001 From: Matt Palmer Date: Mon, 10 Jun 2024 09:40:09 +1000 Subject: [PATCH 60/63] Strip non-address characters from Forwarded for= (#3343) * Strip non-address characters from Forwarded for= This is something of a followup to #2528, which asked for port information to not be included in when it was taken from the local socket. The header's element may optionally contain port information (https://datatracker.ietf.org/doc/html/rfc7239#section-6). However, as I understand it, is *supposed* to only contain an IP address, without port (per #2528). This PR corrects that discrepancy, making it easier to parse the result of this method in application code. There should not be any compatibility concerns, as anyone parsing the output of would already need to handle both port and portless cases anyway. * Update CHANGES.md --------- Co-authored-by: Rob Ede --- actix-web/CHANGES.md | 4 ++++ actix-web/src/info.rs | 28 +++++++++++++++++++++++++--- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 4e74e0902..3d9176dee 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -2,6 +2,10 @@ ## Unreleased +### Fixed + +- `ConnectionInfo::realip_remote_addr()` now handles IPv6 addresses from `Forwarded` header correctly. Previously, it sometimes returned the forwarded port as well. + ## 4.7.0 ### Added diff --git a/actix-web/src/info.rs b/actix-web/src/info.rs index c5d9638f4..aee936ba9 100644 --- a/actix-web/src/info.rs +++ b/actix-web/src/info.rs @@ -21,6 +21,19 @@ fn unquote(val: &str) -> &str { val.trim().trim_start_matches('"').trim_end_matches('"') } +/// Remove port and IPv6 square brackets from a peer specification. +fn bare_address(val: &str) -> &str { + if val.starts_with('[') { + val.split("]:") + .next() + .map(|s| s.trim_start_matches('[').trim_end_matches(']')) + // This shouldn't *actually* ever happen + .unwrap_or(val) + } else { + val.split(':').next().unwrap_or(val) + } +} + /// Extracts and trims first value for given header name. fn first_header_value<'a>(req: &'a RequestHead, name: &'_ HeaderName) -> Option<&'a str> { let hdr = req.headers.get(name)?.to_str().ok()?; @@ -100,7 +113,7 @@ impl ConnectionInfo { // --- https://datatracker.ietf.org/doc/html/rfc7239#section-5.2 match name.trim().to_lowercase().as_str() { - "for" => realip_remote_addr.get_or_insert_with(|| unquote(val)), + "for" => realip_remote_addr.get_or_insert_with(|| bare_address(unquote(val))), "proto" => scheme.get_or_insert_with(|| unquote(val)), "host" => host.get_or_insert_with(|| unquote(val)), "by" => { @@ -368,16 +381,25 @@ mod tests { .insert_header((header::FORWARDED, r#"for="192.0.2.60:8080""#)) .to_http_request(); let info = req.connection_info(); - assert_eq!(info.realip_remote_addr(), Some("192.0.2.60:8080")); + assert_eq!(info.realip_remote_addr(), Some("192.0.2.60")); } #[test] fn forwarded_for_ipv6() { + let req = TestRequest::default() + .insert_header((header::FORWARDED, r#"for="[2001:db8:cafe::17]""#)) + .to_http_request(); + let info = req.connection_info(); + assert_eq!(info.realip_remote_addr(), Some("2001:db8:cafe::17")); + } + + #[test] + fn forwarded_for_ipv6_with_port() { let req = TestRequest::default() .insert_header((header::FORWARDED, r#"for="[2001:db8:cafe::17]:4711""#)) .to_http_request(); let info = req.connection_info(); - assert_eq!(info.realip_remote_addr(), Some("[2001:db8:cafe::17]:4711")); + assert_eq!(info.realip_remote_addr(), Some("2001:db8:cafe::17")); } #[test] From 4908fd7dea00a361cf6b37f9d66f1ac3c4805543 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Jun 2024 01:44:58 +0100 Subject: [PATCH 61/63] build(deps): bump taiki-e/install-action from 2.34.0 to 2.38.0 (#3396) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.34.0 to 2.38.0. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/v2.34.0...v2.38.0) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 4 ++-- .github/workflows/ci.yml | 4 ++-- .github/workflows/coverage.yml | 2 +- .github/workflows/lint.yml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index 4231b4dc2..d0eb3f8fd 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -49,7 +49,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install just, cargo-hack, cargo-nextest, cargo-ci-cache-clean - uses: taiki-e/install-action@v2.34.0 + uses: taiki-e/install-action@v2.38.0 with: tool: just,cargo-hack,cargo-nextest,cargo-ci-cache-clean @@ -80,7 +80,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - name: Install cargo-hack - uses: taiki-e/install-action@v2.34.0 + uses: taiki-e/install-action@v2.38.0 with: tool: cargo-hack diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ab611fc0a..cc51b89f6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -64,7 +64,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install just, cargo-hack, cargo-nextest, cargo-ci-cache-clean - uses: taiki-e/install-action@v2.34.0 + uses: taiki-e/install-action@v2.38.0 with: tool: just,cargo-hack,cargo-nextest,cargo-ci-cache-clean @@ -113,7 +113,7 @@ jobs: toolchain: nightly - name: Install just - uses: taiki-e/install-action@v2.34.0 + uses: taiki-e/install-action@v2.38.0 with: tool: just diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index da892bd7a..5c944bece 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -23,7 +23,7 @@ jobs: components: llvm-tools-preview - name: Install just,cargo-llvm-cov - uses: taiki-e/install-action@v2.34.0 + uses: taiki-e/install-action@v2.38.0 with: tool: just,cargo-llvm-cov diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index dd44d4cb3..d5c667f99 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -82,7 +82,7 @@ jobs: toolchain: nightly-2024-06-07 - name: Install cargo-public-api - uses: taiki-e/install-action@v2.34.0 + uses: taiki-e/install-action@v2.38.0 with: tool: cargo-public-api From 7f529e35b296c8359bdf22e7480722a5844e3ce2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Jun 2024 01:45:11 +0100 Subject: [PATCH 62/63] build(deps): bump actions-rust-lang/setup-rust-toolchain from 1.8.0 to 1.9.0 (#3395) build(deps): bump actions-rust-lang/setup-rust-toolchain Bumps [actions-rust-lang/setup-rust-toolchain](https://github.com/actions-rust-lang/setup-rust-toolchain) from 1.8.0 to 1.9.0. - [Release notes](https://github.com/actions-rust-lang/setup-rust-toolchain/releases) - [Changelog](https://github.com/actions-rust-lang/setup-rust-toolchain/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions-rust-lang/setup-rust-toolchain/compare/v1.8.0...v1.9.0) --- updated-dependencies: - dependency-name: actions-rust-lang/setup-rust-toolchain dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 4 ++-- .github/workflows/ci.yml | 6 +++--- .github/workflows/coverage.yml | 2 +- .github/workflows/lint.yml | 8 ++++---- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index d0eb3f8fd..1729d9a07 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -44,7 +44,7 @@ jobs: 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 + uses: actions-rust-lang/setup-rust-toolchain@v1.9.0 with: toolchain: ${{ matrix.version.version }} @@ -77,7 +77,7 @@ jobs: run: ./scripts/free-disk-space.sh - name: Install Rust - uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 + uses: actions-rust-lang/setup-rust-toolchain@v1.9.0 - name: Install cargo-hack uses: taiki-e/install-action@v2.38.0 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cc51b89f6..1b6f7b460 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -59,7 +59,7 @@ jobs: uses: rui314/setup-mold@v1 - name: Install Rust (${{ matrix.version.name }}) - uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 + uses: actions-rust-lang/setup-rust-toolchain@v1.9.0 with: toolchain: ${{ matrix.version.version }} @@ -92,7 +92,7 @@ jobs: - uses: actions/checkout@v4 - name: Install Rust - uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 + uses: actions-rust-lang/setup-rust-toolchain@v1.9.0 with: toolchain: nightly @@ -108,7 +108,7 @@ jobs: - uses: actions/checkout@v4 - name: Install Rust (nightly) - uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 + uses: actions-rust-lang/setup-rust-toolchain@v1.9.0 with: toolchain: nightly diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 5c944bece..de7fd7031 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -18,7 +18,7 @@ jobs: - uses: actions/checkout@v4 - name: Install Rust - uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 + uses: actions-rust-lang/setup-rust-toolchain@v1.9.0 with: components: llvm-tools-preview diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index d5c667f99..8fe8f59d3 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -18,7 +18,7 @@ jobs: - uses: actions/checkout@v4 - name: Install Rust (nightly) - uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 + uses: actions-rust-lang/setup-rust-toolchain@v1.9.0 with: toolchain: nightly components: rustfmt @@ -36,7 +36,7 @@ jobs: - uses: actions/checkout@v4 - name: Install Rust - uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 + uses: actions-rust-lang/setup-rust-toolchain@v1.9.0 with: components: clippy @@ -55,7 +55,7 @@ jobs: - uses: actions/checkout@v4 - name: Install Rust (nightly) - uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 + uses: actions-rust-lang/setup-rust-toolchain@v1.9.0 with: toolchain: nightly components: rust-docs @@ -77,7 +77,7 @@ jobs: uses: actions/checkout@v4 - name: Install Rust - uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 + uses: actions-rust-lang/setup-rust-toolchain@v1.9.0 with: toolchain: nightly-2024-06-07 From 53086a90a679e609ae6afe43d0eb94cdb270f3c0 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 10 Jun 2024 01:58:13 +0100 Subject: [PATCH 63/63] build: add coverage recipes to justfile --- actix-web/src/info.rs | 3 ++- justfile | 8 ++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/actix-web/src/info.rs b/actix-web/src/info.rs index aee936ba9..1b2e554f9 100644 --- a/actix-web/src/info.rs +++ b/actix-web/src/info.rs @@ -27,7 +27,8 @@ fn bare_address(val: &str) -> &str { val.split("]:") .next() .map(|s| s.trim_start_matches('[').trim_end_matches(']')) - // This shouldn't *actually* ever happen + // this indicates that the IPv6 address is malformed so shouldn't + // usually happen, but if it does, just return the original input .unwrap_or(val) } else { val.split(':').next().unwrap_or(val) diff --git a/justfile b/justfile index 4e106ef11..7f6dbb61e 100644 --- a/justfile +++ b/justfile @@ -53,6 +53,14 @@ test-docs toolchain="": && doc # Test workspace. test-all toolchain="": (test toolchain) (test-docs toolchain) +# Test workspace and generate Codecov coverage file. +test-coverage-codecov toolchain="": + cargo {{ toolchain }} llvm-cov --workspace {{ all_crate_features }} --codecov --output-path codecov.json + +# Test workspace and generate LCOV coverage file. +test-coverage-lcov toolchain="": + cargo {{ toolchain }} llvm-cov --workspace {{ all_crate_features }} --lcov --output-path lcov.info + # Document crates in workspace. doc *args: RUSTDOCFLAGS="--cfg=docsrs -Dwarnings" cargo +nightly doc --no-deps --workspace {{ all_crate_features }} {{ args }}