diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml
index a4b54ca7a..008c33f89 100644
--- a/.github/workflows/bench.yml
+++ b/.github/workflows/bench.yml
@@ -5,6 +5,9 @@ on:
branches:
- master
+permissions:
+ contents: read # to fetch code (actions/checkout)
+
jobs:
check_benchmark:
runs-on: ubuntu-latest
diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml
index 1ee97b591..7ac6388d4 100644
--- a/.github/workflows/ci-post-merge.yml
+++ b/.github/workflows/ci-post-merge.yml
@@ -4,6 +4,9 @@ on:
push:
branches: [master]
+permissions:
+ contents: read # to fetch code (actions/checkout)
+
jobs:
build_and_test_nightly:
strategy:
@@ -92,29 +95,21 @@ jobs:
steps:
- uses: actions/checkout@v2
- - name: Install stable
- uses: actions-rs/toolchain@v1
- with:
- toolchain: stable-x86_64-unknown-linux-gnu
- profile: minimal
- override: true
+ - uses: dtolnay/rust-toolchain@stable
- name: Install cargo-hack
uses: taiki-e/install-action@cargo-hack
- name: Generate Cargo.lock
- uses: actions-rs/cargo@v1
- with: { command: generate-lockfile }
+ run: cargo generate-lockfile
- name: Cache Dependencies
uses: Swatinem/rust-cache@v1.2.0
- name: check feature combinations
- uses: actions-rs/cargo@v1
- with: { command: ci-check-all-feature-powerset }
-
+ run: cargo ci-check-all-feature-powerset
+
- name: check feature combinations
- uses: actions-rs/cargo@v1
- with: { command: ci-check-all-feature-powerset-linux }
+ run: cargo ci-check-all-feature-powerset-linux
nextest:
name: nextest
@@ -127,24 +122,15 @@ jobs:
steps:
- uses: actions/checkout@v2
- - name: Install Rust
- uses: actions-rs/toolchain@v1
- with:
- toolchain: stable
- profile: minimal
- override: true
+ - uses: dtolnay/rust-toolchain@stable
- name: Install nextest
uses: taiki-e/install-action@nextest
- name: Generate Cargo.lock
- uses: actions-rs/cargo@v1
- with: { command: generate-lockfile }
+ run: cargo generate-lockfile
- name: Cache Dependencies
uses: Swatinem/rust-cache@v1.3.0
- name: Test with cargo-nextest
- uses: actions-rs/cargo@v1
- with:
- command: nextest
- args: run
+ run: cargo nextest run
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index de1e1fe18..421becc63 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -6,6 +6,9 @@ on:
push:
branches: [master]
+permissions:
+ contents: read # to fetch code (actions/checkout)
+
jobs:
build_and_test:
strategy:
@@ -63,6 +66,11 @@ jobs:
- name: Cache Dependencies
uses: Swatinem/rust-cache@v1.2.0
+ - name: workaround MSRV issues
+ if: matrix.version != 'stable'
+ run: |
+ cargo update -p=zstd-sys --precise=2.0.1+zstd.1.5.2
+
- name: check minimal
uses: actions-rs/cargo@v1
with: { command: ci-check-min }
@@ -96,16 +104,10 @@ jobs:
steps:
- uses: actions/checkout@v2
- - name: Install Rust
- uses: actions-rs/toolchain@v1
- with:
- toolchain: stable-x86_64-unknown-linux-gnu
- profile: minimal
- override: true
+ - uses: dtolnay/rust-toolchain@stable
- name: Generate Cargo.lock
- uses: actions-rs/cargo@v1
- with: { command: generate-lockfile }
+ run: cargo generate-lockfile
- name: Cache Dependencies
uses: Swatinem/rust-cache@v1.3.0
@@ -123,20 +125,13 @@ jobs:
steps:
- uses: actions/checkout@v2
- - name: Install Rust (nightly)
- uses: actions-rs/toolchain@v1
- with:
- toolchain: nightly-x86_64-unknown-linux-gnu
- profile: minimal
- override: true
+ - uses: dtolnay/rust-toolchain@nightly
- name: Generate Cargo.lock
- uses: actions-rs/cargo@v1
- with: { command: generate-lockfile }
+ run: cargo generate-lockfile
- name: Cache Dependencies
uses: Swatinem/rust-cache@v1.3.0
- name: doc tests
- uses: actions-rs/cargo@v1
+ run: cargo ci-doctest
timeout-minutes: 60
- with: { command: ci-doctest }
diff --git a/.github/workflows/clippy-fmt.yml b/.github/workflows/clippy-fmt.yml
index bc2cec145..e94c4d1af 100644
--- a/.github/workflows/clippy-fmt.yml
+++ b/.github/workflows/clippy-fmt.yml
@@ -9,54 +9,37 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
-
- - name: Install Rust
- uses: actions-rs/toolchain@v1
- with:
- toolchain: stable
- profile: minimal
- components: rustfmt
- - name: Check with rustfmt
- uses: actions-rs/cargo@v1
- with:
- command: fmt
- args: --all -- --check
+ - uses: dtolnay/rust-toolchain@nightly
+ with: { components: rustfmt }
+ - run: cargo fmt --all -- --check
clippy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- - name: Install Rust
- uses: actions-rs/toolchain@v1
- with:
- toolchain: stable
- profile: minimal
- components: clippy
- override: true
+ - uses: dtolnay/rust-toolchain@stable
+ with: { components: clippy }
- name: Generate Cargo.lock
- uses: actions-rs/cargo@v1
- with: { command: generate-lockfile }
+ run: cargo generate-lockfile
- name: Cache Dependencies
uses: Swatinem/rust-cache@v1.2.0
-
+
- name: Check with Clippy
uses: actions-rs/clippy-check@v1
with:
- token: ${{ secrets.GITHUB_TOKEN }}
args: --workspace --tests --examples --all-features
+ token: ${{ secrets.GITHUB_TOKEN }}
lint-docs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- - name: Install Rust
- uses: actions-rs/toolchain@v1
- with:
- toolchain: stable
- profile: minimal
- components: rust-docs
+
+ - uses: dtolnay/rust-toolchain@stable
+ with: { components: rust-docs }
+
- name: Check for broken intra-doc links
uses: actions-rs/cargo@v1
env:
diff --git a/.github/workflows/upload-doc.yml b/.github/workflows/upload-doc.yml
index 07f839e34..9aadafafc 100644
--- a/.github/workflows/upload-doc.yml
+++ b/.github/workflows/upload-doc.yml
@@ -4,31 +4,29 @@ on:
push:
branches: [master]
+permissions: {}
jobs:
build:
+ permissions:
+ contents: write # to push changes in repo (jamesives/github-pages-deploy-action)
+
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- - name: Install Rust
- uses: actions-rs/toolchain@v1
- with:
- toolchain: nightly-x86_64-unknown-linux-gnu
- profile: minimal
- override: true
+ - uses: dtolnay/rust-toolchain@nightly
- name: Build Docs
- uses: actions-rs/cargo@v1
- with:
- command: doc
- args: --workspace --all-features --no-deps
+ 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.4.0
+ uses: JamesIves/github-pages-deploy-action@v4.4.1
with:
folder: target/doc
single-commit: true
diff --git a/actix-files/Cargo.toml b/actix-files/Cargo.toml
index 33de0e6d9..01dc2928a 100644
--- a/actix-files/Cargo.toml
+++ b/actix-files/Cargo.toml
@@ -3,7 +3,6 @@ name = "actix-files"
version = "0.6.2"
authors = [
"Nikolay Kim ",
- "fakeshadow <24548779@qq.com>",
"Rob Ede ",
]
description = "Static file serving for Actix Web"
@@ -30,7 +29,7 @@ actix-web = { version = "4", default-features = false }
bitflags = "1"
bytes = "1"
derive_more = "0.99.5"
-futures-core = { version = "0.3.7", default-features = false, features = ["alloc"] }
+futures-core = { version = "0.3.17", default-features = false, features = ["alloc"] }
http-range = "0.1.4"
log = "0.4"
mime = "0.3"
diff --git a/actix-files/src/lib.rs b/actix-files/src/lib.rs
index 40327e5e8..0fbe39a8e 100644
--- a/actix-files/src/lib.rs
+++ b/actix-files/src/lib.rs
@@ -13,6 +13,7 @@
#![deny(rust_2018_idioms, nonstandard_style)]
#![warn(future_incompatible, missing_docs, missing_debug_implementations)]
+#![allow(clippy::uninlined_format_args)]
use actix_service::boxed::{BoxService, BoxServiceFactory};
use actix_web::{
diff --git a/actix-http-test/Cargo.toml b/actix-http-test/Cargo.toml
index 0a9ddf947..1162c0a38 100644
--- a/actix-http-test/Cargo.toml
+++ b/actix-http-test/Cargo.toml
@@ -39,7 +39,7 @@ awc = { version = "3", default-features = false }
base64 = "0.13"
bytes = "1"
-futures-core = { version = "0.3.7", default-features = false }
+futures-core = { version = "0.3.17", default-features = false }
http = "0.2.5"
log = "0.4"
socket2 = "0.4"
@@ -48,7 +48,7 @@ serde_json = "1.0"
slab = "0.4"
serde_urlencoded = "0.7"
tls-openssl = { version = "0.10.9", package = "openssl", optional = true }
-tokio = { version = "1.8.4", features = ["sync"] }
+tokio = { version = "1.18.4", features = ["sync"] }
[dev-dependencies]
actix-web = { version = "4", default-features = false, features = ["cookies"] }
diff --git a/actix-http-test/src/lib.rs b/actix-http-test/src/lib.rs
index 8636ef9c4..a66f7b486 100644
--- a/actix-http-test/src/lib.rs
+++ b/actix-http-test/src/lib.rs
@@ -2,6 +2,7 @@
#![deny(rust_2018_idioms, nonstandard_style)]
#![warn(future_incompatible)]
+#![allow(clippy::uninlined_format_args)]
#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
@@ -87,6 +88,7 @@ pub async fn test_server_with_addr>(
// notify TestServer that server and system have shut down
// all thread managed resources should be dropped at this point
+ #[allow(clippy::let_underscore_future)]
let _ = thread_stop_tx.send(());
});
@@ -294,6 +296,7 @@ impl Drop for TestServer {
// without needing to await anything
// signal server to stop
+ #[allow(clippy::let_underscore_future)]
let _ = self.server.stop(true);
// signal system to stop
diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md
index a8f65ef92..f67a7fefc 100644
--- a/actix-http/CHANGES.md
+++ b/actix-http/CHANGES.md
@@ -5,14 +5,31 @@
- Fix non-empty body of http2 HEAD response.
### Added
+- Implement `MessageBody` for `Cow<'static, str>` and `Cow<'static, [u8]>`. [#2959]
- Implement `MessageBody` for `&mut B` where `B: MessageBody + Unpin`. [#2868]
- Implement `MessageBody` for `Pin` where `B::Target: MessageBody`. [#2868]
+- Automatic h2c detection via new service finalizer `HttpService::tcp_auto_h2c()`. [#2957]
+- `HeaderMap::retain()` [#2955].
+- Header name constants in `header` module. [#2956] [#2968]
+ - `CACHE_STATUS`
+ - `CDN_CACHE_CONTROL`
+ - `CROSS_ORIGIN_EMBEDDER_POLICY`
+ - `CROSS_ORIGIN_OPENER_POLICY`
+ - `PERMISSIONS_POLICY`
+ - `X_FORWARDED_FOR`
+ - `X_FORWARDED_HOST`
+ - `X_FORWARDED_PROTO`
### Performance
- Improve overall performance of operations on `Extensions`. [#2890]
+[#2959]: https://github.com/actix/actix-web/pull/2959
[#2868]: https://github.com/actix/actix-web/pull/2868
[#2890]: https://github.com/actix/actix-web/pull/2890
+[#2957]: https://github.com/actix/actix-web/pull/2957
+[#2955]: https://github.com/actix/actix-web/pull/2955
+[#2956]: https://github.com/actix/actix-web/pull/2956
+[#2968]: https://github.com/actix/actix-web/pull/2968
## 3.2.2 - 2022-09-11
diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml
index 30e436160..9939089b9 100644
--- a/actix-http/Cargo.toml
+++ b/actix-http/Cargo.toml
@@ -67,7 +67,7 @@ bytes = "1"
bytestring = "1"
derive_more = "0.99.5"
encoding_rs = "0.8"
-futures-core = { version = "0.3.7", default-features = false, features = ["alloc"] }
+futures-core = { version = "0.3.17", default-features = false, features = ["alloc"] }
http = "0.2.5"
httparse = "1.5.1"
httpdate = "1.0.1"
@@ -77,6 +77,8 @@ mime = "0.3"
percent-encoding = "2.1"
pin-project-lite = "0.2"
smallvec = "1.6.1"
+tokio = { version = "1.18.4", features = [] }
+tokio-util = { version = "0.7", features = ["io", "codec"] }
tracing = { version = "0.1.30", default-features = false, features = ["log"] }
# http2
@@ -94,7 +96,7 @@ actix-tls = { version = "3", default-features = false, optional = true }
# compress-*
brotli = { version = "3.3.3", optional = true }
flate2 = { version = "1.0.13", optional = true }
-zstd = { version = "0.11", optional = true }
+zstd = { version = "0.12", optional = true }
[dev-dependencies]
actix-http-test = { version = "3", features = ["openssl"] }
@@ -103,9 +105,9 @@ actix-tls = { version = "3", features = ["openssl"] }
actix-web = "4"
async-stream = "0.3"
-criterion = { version = "0.3", features = ["html_reports"] }
+criterion = { version = "0.4", features = ["html_reports"] }
env_logger = "0.9"
-futures-util = { version = "0.3.7", default-features = false, features = ["alloc"] }
+futures-util = { version = "0.3.17", default-features = false, features = ["alloc"] }
memchr = "2.4"
once_cell = "1.9"
rcgen = "0.9"
@@ -117,7 +119,7 @@ serde_json = "1.0"
static_assertions = "1"
tls-openssl = { package = "openssl", version = "0.10.9" }
tls-rustls = { package = "rustls", version = "0.20.0" }
-tokio = { version = "1.8.4", features = ["net", "rt", "macros"] }
+tokio = { version = "1.18.4", features = ["net", "rt", "macros"] }
[[example]]
name = "ws"
diff --git a/actix-http/benches/quality-value.rs b/actix-http/benches/quality-value.rs
index 33ba9c4c8..0ed274ded 100644
--- a/actix-http/benches/quality-value.rs
+++ b/actix-http/benches/quality-value.rs
@@ -1,3 +1,5 @@
+#![allow(clippy::uninlined_format_args)]
+
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
const CODES: &[u16] = &[0, 1000, 201, 800, 550];
diff --git a/actix-http/examples/h2c-detect.rs b/actix-http/examples/h2c-detect.rs
new file mode 100644
index 000000000..aa3dd5d31
--- /dev/null
+++ b/actix-http/examples/h2c-detect.rs
@@ -0,0 +1,29 @@
+//! An example that supports automatic selection of plaintext h1/h2c connections.
+//!
+//! Notably, both the following commands will work.
+//! ```console
+//! $ curl --http1.1 'http://localhost:8080/'
+//! $ curl --http2-prior-knowledge 'http://localhost:8080/'
+//! ```
+
+use std::{convert::Infallible, io};
+
+use actix_http::{HttpService, Request, Response, StatusCode};
+use actix_server::Server;
+
+#[tokio::main(flavor = "current_thread")]
+async fn main() -> io::Result<()> {
+ env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
+
+ Server::build()
+ .bind("h2c-detect", ("127.0.0.1", 8080), || {
+ HttpService::build()
+ .finish(|_req: Request| async move {
+ Ok::<_, Infallible>(Response::build(StatusCode::OK).body("Hello!"))
+ })
+ .tcp_auto_h2c()
+ })?
+ .workers(2)
+ .run()
+ .await
+}
diff --git a/actix-http/examples/ws.rs b/actix-http/examples/ws.rs
index c4f0503cd..6af6d5095 100644
--- a/actix-http/examples/ws.rs
+++ b/actix-http/examples/ws.rs
@@ -10,13 +10,13 @@ use std::{
time::Duration,
};
-use actix_codec::Encoder;
use actix_http::{body::BodyStream, error::Error, ws, HttpService, Request, Response};
use actix_rt::time::{interval, Interval};
use actix_server::Server;
use bytes::{Bytes, BytesMut};
use bytestring::ByteString;
use futures_core::{ready, Stream};
+use tokio_util::codec::Encoder;
use tracing::{info, trace};
#[actix_rt::main]
diff --git a/actix-http/src/body/message_body.rs b/actix-http/src/body/message_body.rs
index 0cfaa8653..e274cf8aa 100644
--- a/actix-http/src/body/message_body.rs
+++ b/actix-http/src/body/message_body.rs
@@ -120,7 +120,7 @@ pub trait MessageBody {
}
mod foreign_impls {
- use std::ops::DerefMut;
+ use std::{borrow::Cow, ops::DerefMut};
use super::*;
@@ -324,6 +324,39 @@ mod foreign_impls {
}
}
+ impl MessageBody for Cow<'static, [u8]> {
+ type Error = Infallible;
+
+ #[inline]
+ fn size(&self) -> BodySize {
+ BodySize::Sized(self.len() as u64)
+ }
+
+ #[inline]
+ fn poll_next(
+ self: Pin<&mut Self>,
+ _cx: &mut Context<'_>,
+ ) -> Poll