Merge branch 'main' into feat/implement-multipartform-handling-for-optional-vector

This commit is contained in:
fasilmveloor 2025-12-14 19:12:57 +05:30 committed by GitHub
commit 7f57a87d78
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
40 changed files with 483 additions and 858 deletions

View File

@ -16,7 +16,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Install Rust - name: Install Rust
run: | run: |

View File

@ -28,7 +28,7 @@ jobs:
runs-on: ${{ matrix.target.os }} runs-on: ${{ matrix.target.os }}
steps: steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Install nasm - name: Install nasm
if: matrix.target.os == 'windows-latest' if: matrix.target.os == 'windows-latest'
@ -49,7 +49,7 @@ jobs:
toolchain: ${{ matrix.version.version }} toolchain: ${{ matrix.version.version }}
- name: Install just, cargo-hack, cargo-nextest, cargo-ci-cache-clean - name: Install just, cargo-hack, cargo-nextest, cargo-ci-cache-clean
uses: taiki-e/install-action@0be4756f42223b67aa4b7df5effad59010cbf4b9 # v2.62.51 uses: taiki-e/install-action@50708e9ba8d7b6587a2cb575ddaa9a62e927bc06 # v2.62.63
with: with:
tool: just,cargo-hack,cargo-nextest,cargo-ci-cache-clean tool: just,cargo-hack,cargo-nextest,cargo-ci-cache-clean
@ -71,7 +71,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Free Disk Space - name: Free Disk Space
run: ./scripts/free-disk-space.sh run: ./scripts/free-disk-space.sh
@ -83,7 +83,7 @@ jobs:
uses: actions-rust-lang/setup-rust-toolchain@1780873c7b576612439a134613cc4cc74ce5538c # v1.15.2 uses: actions-rust-lang/setup-rust-toolchain@1780873c7b576612439a134613cc4cc74ce5538c # v1.15.2
- name: Install just, cargo-hack - name: Install just, cargo-hack
uses: taiki-e/install-action@0be4756f42223b67aa4b7df5effad59010cbf4b9 # v2.62.51 uses: taiki-e/install-action@50708e9ba8d7b6587a2cb575ddaa9a62e927bc06 # v2.62.63
with: with:
tool: just,cargo-hack tool: just,cargo-hack

View File

@ -39,7 +39,7 @@ jobs:
runs-on: ${{ matrix.target.os }} runs-on: ${{ matrix.target.os }}
steps: steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Install nasm - name: Install nasm
if: matrix.target.os == 'windows-latest' if: matrix.target.os == 'windows-latest'
@ -64,7 +64,7 @@ jobs:
toolchain: ${{ matrix.version.version }} toolchain: ${{ matrix.version.version }}
- name: Install just, cargo-hack, cargo-nextest, cargo-ci-cache-clean - name: Install just, cargo-hack, cargo-nextest, cargo-ci-cache-clean
uses: taiki-e/install-action@0be4756f42223b67aa4b7df5effad59010cbf4b9 # v2.62.51 uses: taiki-e/install-action@50708e9ba8d7b6587a2cb575ddaa9a62e927bc06 # v2.62.63
with: with:
tool: just,cargo-hack,cargo-nextest,cargo-ci-cache-clean tool: just,cargo-hack,cargo-nextest,cargo-ci-cache-clean
@ -87,13 +87,13 @@ jobs:
- name: deny check - name: deny check
if: matrix.version.name == 'stable' && matrix.target.os == 'ubuntu-latest' if: matrix.version.name == 'stable' && matrix.target.os == 'ubuntu-latest'
uses: EmbarkStudios/cargo-deny-action@f2ba7abc2abebaf185c833c3961145a3c275caad # v2.0.13 uses: EmbarkStudios/cargo-deny-action@76cd80eb775d7bbbd2d80292136d74d39e1b4918 # v2.0.14
io-uring: io-uring:
name: io-uring tests name: io-uring tests
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Install Rust - name: Install Rust
uses: actions-rust-lang/setup-rust-toolchain@1780873c7b576612439a134613cc4cc74ce5538c # v1.15.2 uses: actions-rust-lang/setup-rust-toolchain@1780873c7b576612439a134613cc4cc74ce5538c # v1.15.2
@ -109,7 +109,7 @@ jobs:
name: doc tests name: doc tests
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Install Rust (nightly) - name: Install Rust (nightly)
uses: actions-rust-lang/setup-rust-toolchain@1780873c7b576612439a134613cc4cc74ce5538c # v1.15.2 uses: actions-rust-lang/setup-rust-toolchain@1780873c7b576612439a134613cc4cc74ce5538c # v1.15.2
@ -117,7 +117,7 @@ jobs:
toolchain: nightly toolchain: nightly
- name: Install just - name: Install just
uses: taiki-e/install-action@0be4756f42223b67aa4b7df5effad59010cbf4b9 # v2.62.51 uses: taiki-e/install-action@50708e9ba8d7b6587a2cb575ddaa9a62e927bc06 # v2.62.63
with: with:
tool: just tool: just

View File

@ -15,7 +15,7 @@ jobs:
coverage: coverage:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Install Rust (nightly) - name: Install Rust (nightly)
uses: actions-rust-lang/setup-rust-toolchain@1780873c7b576612439a134613cc4cc74ce5538c # v1.15.2 uses: actions-rust-lang/setup-rust-toolchain@1780873c7b576612439a134613cc4cc74ce5538c # v1.15.2
@ -24,7 +24,7 @@ jobs:
components: llvm-tools components: llvm-tools
- name: Install just, cargo-llvm-cov, cargo-nextest - name: Install just, cargo-llvm-cov, cargo-nextest
uses: taiki-e/install-action@0be4756f42223b67aa4b7df5effad59010cbf4b9 # v2.62.51 uses: taiki-e/install-action@50708e9ba8d7b6587a2cb575ddaa9a62e927bc06 # v2.62.63
with: with:
tool: just,cargo-llvm-cov,cargo-nextest tool: just,cargo-llvm-cov,cargo-nextest

View File

@ -15,7 +15,7 @@ jobs:
fmt: fmt:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Install Rust (nightly) - name: Install Rust (nightly)
uses: actions-rust-lang/setup-rust-toolchain@1780873c7b576612439a134613cc4cc74ce5538c # v1.15.2 uses: actions-rust-lang/setup-rust-toolchain@1780873c7b576612439a134613cc4cc74ce5538c # v1.15.2
@ -33,7 +33,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Install Rust - name: Install Rust
uses: actions-rust-lang/setup-rust-toolchain@1780873c7b576612439a134613cc4cc74ce5538c # v1.15.2 uses: actions-rust-lang/setup-rust-toolchain@1780873c7b576612439a134613cc4cc74ce5538c # v1.15.2
@ -52,7 +52,7 @@ jobs:
lint-docs: lint-docs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Install Rust (nightly) - name: Install Rust (nightly)
uses: actions-rust-lang/setup-rust-toolchain@1780873c7b576612439a134613cc4cc74ce5538c # v1.15.2 uses: actions-rust-lang/setup-rust-toolchain@1780873c7b576612439a134613cc4cc74ce5538c # v1.15.2
@ -69,7 +69,7 @@ jobs:
if: false # rustdoc mismatch currently if: false # rustdoc mismatch currently
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Install Rust (${{ vars.RUST_VERSION_EXTERNAL_TYPES }}) - name: Install Rust (${{ vars.RUST_VERSION_EXTERNAL_TYPES }})
uses: actions-rust-lang/setup-rust-toolchain@1780873c7b576612439a134613cc4cc74ce5538c # v1.15.2 uses: actions-rust-lang/setup-rust-toolchain@1780873c7b576612439a134613cc4cc74ce5538c # v1.15.2
@ -77,7 +77,7 @@ jobs:
toolchain: ${{ vars.RUST_VERSION_EXTERNAL_TYPES }} toolchain: ${{ vars.RUST_VERSION_EXTERNAL_TYPES }}
- name: Install just - name: Install just
uses: taiki-e/install-action@0be4756f42223b67aa4b7df5effad59010cbf4b9 # v2.62.51 uses: taiki-e/install-action@50708e9ba8d7b6587a2cb575ddaa9a62e927bc06 # v2.62.63
with: with:
tool: just tool: just

1010
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -19,7 +19,7 @@ homepage = "https://actix.rs"
repository = "https://github.com/actix/actix-web" repository = "https://github.com/actix/actix-web"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
edition = "2021" edition = "2021"
rust-version = "1.75" rust-version = "1.82"
[profile.dev] [profile.dev]
# Disabling debug info speeds up builds a bunch and we don't rely on it for debugging that much. # Disabling debug info speeds up builds a bunch and we don't rely on it for debugging that much.

View File

@ -2,6 +2,12 @@
## Unreleased ## Unreleased
- Minimum supported Rust version (MSRV) is now 1.82.
## 0.6.9
- Correct `derive_more` dependency feature requirements.
## 0.6.8 ## 0.6.8
- Add `Files::with_permanent_redirect()` method. - Add `Files::with_permanent_redirect()` method.

View File

@ -1,6 +1,6 @@
[package] [package]
name = "actix-files" name = "actix-files"
version = "0.6.8" version = "0.6.9"
authors = ["Nikolay Kim <fafhrd91@gmail.com>", "Rob Ede <robjtede@icloud.com>"] authors = ["Nikolay Kim <fafhrd91@gmail.com>", "Rob Ede <robjtede@icloud.com>"]
description = "Static file serving for Actix Web" description = "Static file serving for Actix Web"
keywords = ["actix", "http", "async", "futures"] keywords = ["actix", "http", "async", "futures"]
@ -24,7 +24,7 @@ actix-web = { version = "4", default-features = false }
bitflags = "2" bitflags = "2"
bytes = "1" bytes = "1"
derive_more = { version = "2", features = ["display", "error", "from"] } derive_more = { version = "2", features = ["deref", "deref_mut", "display", "error", "from"] }
futures-core = { version = "0.3.17", default-features = false, features = ["alloc"] } futures-core = { version = "0.3.17", default-features = false, features = ["alloc"] }
http-range = "0.1.4" http-range = "0.1.4"
log = "0.4" log = "0.4"
@ -37,7 +37,7 @@ v_htmlescape = "0.15.5"
# experimental-io-uring # experimental-io-uring
[target.'cfg(target_os = "linux")'.dependencies] [target.'cfg(target_os = "linux")'.dependencies]
tokio-uring = { version = "0.5", optional = true, features = ["bytes"] } tokio-uring = { version = "0.5", optional = true, features = ["bytes"] }
actix-server = { version = "2.4", optional = true } # ensure matching tokio-uring versions actix-server = { version = "2.4", optional = true } # ensure matching tokio-uring versions
[dev-dependencies] [dev-dependencies]
actix-rt = "2.7" actix-rt = "2.7"

View File

@ -3,11 +3,11 @@
<!-- prettier-ignore-start --> <!-- prettier-ignore-start -->
[![crates.io](https://img.shields.io/crates/v/actix-files?label=latest)](https://crates.io/crates/actix-files) [![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.8)](https://docs.rs/actix-files/0.6.8) [![Documentation](https://docs.rs/actix-files/badge.svg?version=0.6.9)](https://docs.rs/actix-files/0.6.9)
![Version](https://img.shields.io/badge/rustc-1.72+-ab6000.svg) ![Version](https://img.shields.io/badge/rustc-1.72+-ab6000.svg)
![License](https://img.shields.io/crates/l/actix-files.svg) ![License](https://img.shields.io/crates/l/actix-files.svg)
<br /> <br />
[![dependency status](https://deps.rs/crate/actix-files/0.6.8/status.svg)](https://deps.rs/crate/actix-files/0.6.8) [![dependency status](https://deps.rs/crate/actix-files/0.6.9/status.svg)](https://deps.rs/crate/actix-files/0.6.9)
[![Download](https://img.shields.io/crates/d/actix-files.svg)](https://crates.io/crates/actix-files) [![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) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x)

View File

@ -294,16 +294,11 @@ mod tests {
let res = HttpRange::parse(header, size); let res = HttpRange::parse(header, size);
if res.is_err() { if let Err(err) = res {
if expected.is_empty() { if expected.is_empty() {
continue; continue;
} else { } else {
panic!( panic!("parse({header}, {size}) returned error {err:?}");
"parse({}, {}) returned error {:?}",
header,
size,
res.unwrap_err()
);
} }
} }

View File

@ -2,7 +2,7 @@
## Unreleased ## Unreleased
- Minimum supported Rust version (MSRV) is now 1.72. - Minimum supported Rust version (MSRV) is now 1.82.
## 3.2.0 ## 3.2.0

View File

@ -2,6 +2,8 @@
## Unreleased ## Unreleased
- Minimum supported Rust version (MSRV) is now 1.82.
## 3.11.2 ## 3.11.2
- Properly wake Payload receivers when feeding errors or EOF. - Properly wake Payload receivers when feeding errors or EOF.

View File

@ -149,7 +149,7 @@ memchr = "2.4"
once_cell = "1.21" once_cell = "1.21"
rcgen = "0.13" rcgen = "0.13"
regex = "1.3" regex = "1.3"
rustls-pemfile = "2" rustls-pki-types = "1.13.1"
rustversion = "1" rustversion = "1"
serde = { version = "1", features = ["derive"] } serde = { version = "1", features = ["derive"] }
serde_json = "1.0" serde_json = "1.0"

View File

@ -45,25 +45,14 @@ async fn main() -> io::Result<()> {
fn rustls_config() -> rustls::ServerConfig { fn rustls_config() -> rustls::ServerConfig {
let rcgen::CertifiedKey { cert, key_pair } = let rcgen::CertifiedKey { cert, key_pair } =
rcgen::generate_simple_self_signed(["localhost".to_owned()]).unwrap(); rcgen::generate_simple_self_signed(["localhost".to_owned()]).unwrap();
let cert_file = cert.pem(); let cert_chain = vec![cert.der().clone()];
let key_file = key_pair.serialize_pem(); let key_der = rustls_pki_types::PrivateKeyDer::Pkcs8(
rustls_pki_types::PrivatePkcs8KeyDer::from(key_pair.serialize_der()),
let cert_file = &mut io::BufReader::new(cert_file.as_bytes()); );
let key_file = &mut io::BufReader::new(key_file.as_bytes());
let cert_chain = rustls_pemfile::certs(cert_file)
.collect::<Result<Vec<_>, _>>()
.unwrap();
let mut keys = rustls_pemfile::pkcs8_private_keys(key_file)
.collect::<Result<Vec<_>, _>>()
.unwrap();
let mut config = rustls::ServerConfig::builder() let mut config = rustls::ServerConfig::builder()
.with_no_client_auth() .with_no_client_auth()
.with_single_cert( .with_single_cert(cert_chain, key_der)
cert_chain,
rustls::pki_types::PrivateKeyDer::Pkcs8(keys.remove(0)),
)
.unwrap(); .unwrap();
const H1_ALPN: &[u8] = b"http/1.1"; const H1_ALPN: &[u8] = b"http/1.1";

View File

@ -82,29 +82,16 @@ impl Stream for Heartbeat {
} }
fn tls_config() -> rustls::ServerConfig { fn tls_config() -> rustls::ServerConfig {
use std::io::BufReader;
use rustls_pemfile::{certs, pkcs8_private_keys};
let rcgen::CertifiedKey { cert, key_pair } = let rcgen::CertifiedKey { cert, key_pair } =
rcgen::generate_simple_self_signed(["localhost".to_owned()]).unwrap(); rcgen::generate_simple_self_signed(["localhost".to_owned()]).unwrap();
let cert_file = cert.pem(); let cert_chain = vec![cert.der().clone()];
let key_file = key_pair.serialize_pem(); let key_der = rustls_pki_types::PrivateKeyDer::Pkcs8(
rustls_pki_types::PrivatePkcs8KeyDer::from(key_pair.serialize_der()),
let cert_file = &mut BufReader::new(cert_file.as_bytes()); );
let key_file = &mut BufReader::new(key_file.as_bytes());
let cert_chain = certs(cert_file).collect::<Result<Vec<_>, _>>().unwrap();
let mut keys = pkcs8_private_keys(key_file)
.collect::<Result<Vec<_>, _>>()
.unwrap();
let mut config = rustls::ServerConfig::builder() let mut config = rustls::ServerConfig::builder()
.with_no_client_auth() .with_no_client_auth()
.with_single_cert( .with_single_cert(cert_chain, key_der)
cert_chain,
rustls::pki_types::PrivateKeyDer::Pkcs8(keys.remove(0)),
)
.unwrap(); .unwrap();
config.alpn_protocols.push(b"http/1.1".to_vec()); config.alpn_protocols.push(b"http/1.1".to_vec());

View File

@ -176,11 +176,7 @@ impl Inner {
/// Register future waiting data from payload. /// Register future waiting data from payload.
/// Waker would be used in `Inner::wake` /// Waker would be used in `Inner::wake`
fn register(&mut self, cx: &Context<'_>) { fn register(&mut self, cx: &Context<'_>) {
if self if self.task.as_ref().is_none_or(|w| !cx.waker().will_wake(w)) {
.task
.as_ref()
.map_or(true, |w| !cx.waker().will_wake(w))
{
self.task = Some(cx.waker().clone()); self.task = Some(cx.waker().clone());
} }
} }
@ -191,7 +187,7 @@ impl Inner {
if self if self
.io_task .io_task
.as_ref() .as_ref()
.map_or(true, |w| !cx.waker().will_wake(w)) .is_none_or(|w| !cx.waker().will_wake(w))
{ {
self.io_task = Some(cx.waker().clone()); self.io_task = Some(cx.waker().clone());
} }

View File

@ -4,7 +4,7 @@ extern crate tls_rustls_023 as rustls;
use std::{ use std::{
convert::Infallible, convert::Infallible,
io::{self, BufReader, Write}, io::{self, Write},
net::{SocketAddr, TcpStream as StdTcpStream}, net::{SocketAddr, TcpStream as StdTcpStream},
sync::Arc, sync::Arc,
task::Poll, task::Poll,
@ -27,7 +27,7 @@ use derive_more::{Display, Error};
use futures_core::{ready, Stream}; use futures_core::{ready, Stream};
use futures_util::stream::once; use futures_util::stream::once;
use rustls::{pki_types::ServerName, ServerConfig as RustlsServerConfig}; use rustls::{pki_types::ServerName, ServerConfig as RustlsServerConfig};
use rustls_pemfile::{certs, pkcs8_private_keys}; use rustls_pki_types::{PrivateKeyDer, PrivatePkcs8KeyDer};
async fn load_body<S>(stream: S) -> Result<BytesMut, PayloadError> async fn load_body<S>(stream: S) -> Result<BytesMut, PayloadError>
where where
@ -54,23 +54,12 @@ where
fn tls_config() -> RustlsServerConfig { fn tls_config() -> RustlsServerConfig {
let rcgen::CertifiedKey { cert, key_pair } = let rcgen::CertifiedKey { cert, key_pair } =
rcgen::generate_simple_self_signed(["localhost".to_owned()]).unwrap(); rcgen::generate_simple_self_signed(["localhost".to_owned()]).unwrap();
let cert_file = cert.pem(); let cert_chain = vec![cert.der().clone()];
let key_file = key_pair.serialize_pem(); let key_der = PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from(key_pair.serialize_der()));
let cert_file = &mut BufReader::new(cert_file.as_bytes());
let key_file = &mut BufReader::new(key_file.as_bytes());
let cert_chain = certs(cert_file).collect::<Result<Vec<_>, _>>().unwrap();
let mut keys = pkcs8_private_keys(key_file)
.collect::<Result<Vec<_>, _>>()
.unwrap();
let mut config = RustlsServerConfig::builder() let mut config = RustlsServerConfig::builder()
.with_no_client_auth() .with_no_client_auth()
.with_single_cert( .with_single_cert(cert_chain, key_der)
cert_chain,
rustls::pki_types::PrivateKeyDer::Pkcs8(keys.remove(0)),
)
.unwrap(); .unwrap();
config.alpn_protocols.push(HTTP1_1_ALPN_PROTOCOL.to_vec()); config.alpn_protocols.push(HTTP1_1_ALPN_PROTOCOL.to_vec());

View File

@ -2,6 +2,8 @@
## Unreleased ## Unreleased
- Minimum supported Rust version (MSRV) is now 1.82.
## 0.7.0 ## 0.7.0
- Minimum supported Rust version (MSRV) is now 1.72. - Minimum supported Rust version (MSRV) is now 1.72.

View File

@ -16,19 +16,14 @@ use proc_macro2::Ident;
use quote::quote; use quote::quote;
use syn::{parse_macro_input, Type}; use syn::{parse_macro_input, Type};
#[derive(FromMeta)] #[derive(Default, FromMeta)]
enum DuplicateField { enum DuplicateField {
#[default]
Ignore, Ignore,
Deny, Deny,
Replace, Replace,
} }
impl Default for DuplicateField {
fn default() -> Self {
Self::Ignore
}
}
#[derive(FromDeriveInput, Default)] #[derive(FromDeriveInput, Default)]
#[darling(attributes(multipart), default)] #[darling(attributes(multipart), default)]
struct MultipartFormAttrs { struct MultipartFormAttrs {

View File

@ -1,10 +1,10 @@
error: Could not parse size limit `2 bytes`: couldn't parse "bytes" into a known SI unit, couldn't parse unit of "bytes" error: Could not parse size limit `2 bytes`: couldn't parse "bytes" into a known SI unit, Failed to parse unit "byt..."
--> tests/trybuild/size-limit-parse-fail.rs:6:5 --> tests/trybuild/size-limit-parse-fail.rs:6:5
| |
6 | description: Text<String>, 6 | description: Text<String>,
| ^^^^^^^^^^^ | ^^^^^^^^^^^
error: Could not parse size limit `2 megabytes`: couldn't parse "megabytes" into a known SI unit, couldn't parse unit of "megabytes" error: Could not parse size limit `2 megabytes`: couldn't parse "megabytes" into a known SI unit, Failed to parse unit "meg..."
--> tests/trybuild/size-limit-parse-fail.rs:12:5 --> tests/trybuild/size-limit-parse-fail.rs:12:5
| |
12 | description: Text<String>, 12 | description: Text<String>,

View File

@ -2,7 +2,7 @@
## Unreleased ## Unreleased
- Minimum supported Rust version (MSRV) is now 1.75. - Minimum supported Rust version (MSRV) is now 1.82.
## 0.7.2 ## 0.7.2

View File

@ -2,6 +2,8 @@
## Unreleased ## Unreleased
- Minimum supported Rust version (MSRV) is now 1.82.
## 0.5.3 ## 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. - 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.

View File

@ -2,6 +2,8 @@
## Unreleased ## Unreleased
- Minimum supported Rust version (MSRV) is now 1.82.
## 0.1.5 ## 0.1.5
- Add `TestServerConfig::listen_address()` method. - Add `TestServerConfig::listen_address()` method.

View File

@ -2,6 +2,8 @@
## Unreleased ## Unreleased
- Minimum supported Rust version (MSRV) is now 1.82.
## 4.3.1 <!-- v4.3.1+deprecated --> ## 4.3.1 <!-- v4.3.1+deprecated -->
- Reduce memory usage by `take`-ing (rather than `split`-ing) the encoded buffer when yielding bytes in the response stream. - Reduce memory usage by `take`-ing (rather than `split`-ing) the encoded buffer when yielding bytes in the response stream.

View File

@ -2,6 +2,8 @@
## Unreleased ## Unreleased
- Minimum supported Rust version (MSRV) is now 1.82.
## 4.3.0 ## 4.3.0
- Add `#[scope]` macro. - Add `#[scope]` macro.

View File

@ -13,14 +13,14 @@ error[E0277]: the trait bound `fn() -> impl std::future::Future<Output = String>
| required by a bound introduced by this call | required by a bound introduced by this call
| |
= help: the following other types implement trait `HttpServiceFactory`: = help: the following other types implement trait `HttpServiceFactory`:
Resource<T>
actix_web::Scope<T>
Vec<T>
Redirect
(A,)
(A, B) (A, B)
(A, B, C) (A, B, C)
(A, B, C, D) (A, B, C, D)
(A, B, C, D, E)
(A, B, C, D, E, F)
(A, B, C, D, E, F, G)
(A, B, C, D, E, F, G, H)
(A, B, C, D, E, F, G, H, I)
and $N others and $N others
note: required by a bound in `App::<T>::service` note: required by a bound in `App::<T>::service`
--> $WORKSPACE/actix-web/src/app.rs --> $WORKSPACE/actix-web/src/app.rs

View File

@ -13,14 +13,14 @@ error[E0277]: the trait bound `fn() -> impl std::future::Future<Output = String>
| required by a bound introduced by this call | required by a bound introduced by this call
| |
= help: the following other types implement trait `HttpServiceFactory`: = help: the following other types implement trait `HttpServiceFactory`:
Resource<T>
actix_web::Scope<T>
Vec<T>
Redirect
(A,)
(A, B) (A, B)
(A, B, C) (A, B, C)
(A, B, C, D) (A, B, C, D)
(A, B, C, D, E)
(A, B, C, D, E, F)
(A, B, C, D, E, F, G)
(A, B, C, D, E, F, G, H)
(A, B, C, D, E, F, G, H, I)
and $N others and $N others
note: required by a bound in `App::<T>::service` note: required by a bound in `App::<T>::service`
--> $WORKSPACE/actix-web/src/app.rs --> $WORKSPACE/actix-web/src/app.rs

View File

@ -15,14 +15,14 @@ error[E0277]: the trait bound `fn() -> impl std::future::Future<Output = String>
| required by a bound introduced by this call | required by a bound introduced by this call
| |
= help: the following other types implement trait `HttpServiceFactory`: = help: the following other types implement trait `HttpServiceFactory`:
Resource<T>
actix_web::Scope<T>
Vec<T>
Redirect
(A,)
(A, B) (A, B)
(A, B, C) (A, B, C)
(A, B, C, D) (A, B, C, D)
(A, B, C, D, E)
(A, B, C, D, E, F)
(A, B, C, D, E, F, G)
(A, B, C, D, E, F, G, H)
(A, B, C, D, E, F, G, H, I)
and $N others and $N others
note: required by a bound in `App::<T>::service` note: required by a bound in `App::<T>::service`
--> $WORKSPACE/actix-web/src/app.rs --> $WORKSPACE/actix-web/src/app.rs

View File

@ -29,14 +29,14 @@ error[E0277]: the trait bound `fn() -> impl std::future::Future<Output = String>
| required by a bound introduced by this call | required by a bound introduced by this call
| |
= help: the following other types implement trait `HttpServiceFactory`: = help: the following other types implement trait `HttpServiceFactory`:
Resource<T>
actix_web::Scope<T>
Vec<T>
Redirect
(A,)
(A, B) (A, B)
(A, B, C) (A, B, C)
(A, B, C, D) (A, B, C, D)
(A, B, C, D, E)
(A, B, C, D, E, F)
(A, B, C, D, E, F, G)
(A, B, C, D, E, F, G, H)
(A, B, C, D, E, F, G, H, I)
and $N others and $N others
note: required by a bound in `App::<T>::service` note: required by a bound in `App::<T>::service`
--> $WORKSPACE/actix-web/src/app.rs --> $WORKSPACE/actix-web/src/app.rs

View File

@ -15,14 +15,14 @@ error[E0277]: the trait bound `fn() -> impl std::future::Future<Output = String>
| required by a bound introduced by this call | required by a bound introduced by this call
| |
= help: the following other types implement trait `HttpServiceFactory`: = help: the following other types implement trait `HttpServiceFactory`:
Resource<T>
actix_web::Scope<T>
Vec<T>
Redirect
(A,)
(A, B) (A, B)
(A, B, C) (A, B, C)
(A, B, C, D) (A, B, C, D)
(A, B, C, D, E)
(A, B, C, D, E, F)
(A, B, C, D, E, F, G)
(A, B, C, D, E, F, G, H)
(A, B, C, D, E, F, G, H, I)
and $N others and $N others
note: required by a bound in `App::<T>::service` note: required by a bound in `App::<T>::service`
--> $WORKSPACE/actix-web/src/app.rs --> $WORKSPACE/actix-web/src/app.rs

View File

@ -2,6 +2,12 @@
## Unreleased ## Unreleased
- Minimum supported Rust version (MSRV) is now 1.82.
## 4.12.1
- Correct `actix-http` dependency requirement.
## 4.12.0 ## 4.12.0
- `actix_web::response::builder::HttpResponseBuilder::streaming()` now sets `Content-Type` to `application/octet-stream` if `Content-Type` does not exist. - `actix_web::response::builder::HttpResponseBuilder::streaming()` now sets `Content-Type` to `application/octet-stream` if `Content-Type` does not exist.

View File

@ -1,6 +1,6 @@
[package] [package]
name = "actix-web" name = "actix-web"
version = "4.12.0" version = "4.12.1"
description = "Actix Web is a powerful, pragmatic, and extremely fast web framework for Rust" description = "Actix Web is a powerful, pragmatic, and extremely fast web framework for Rust"
authors = ["Nikolay Kim <fafhrd91@gmail.com>", "Rob Ede <robjtede@icloud.com>"] authors = ["Nikolay Kim <fafhrd91@gmail.com>", "Rob Ede <robjtede@icloud.com>"]
keywords = ["actix", "http", "web", "framework", "async"] keywords = ["actix", "http", "web", "framework", "async"]
@ -134,7 +134,7 @@ actix-service = "2"
actix-tls = { version = "3.4", default-features = false, optional = true } actix-tls = { version = "3.4", default-features = false, optional = true }
actix-utils = "3" actix-utils = "3"
actix-http = "3.11" actix-http = "3.11.2"
actix-router = { version = "0.5.3", default-features = false, features = ["http"] } actix-router = { version = "0.5.3", default-features = false, features = ["http"] }
actix-web-codegen = { version = "4.3", optional = true, default-features = false } actix-web-codegen = { version = "4.3", optional = true, default-features = false }
@ -179,7 +179,7 @@ flate2 = "1.0.13"
futures-util = { version = "0.3.17", default-features = false, features = ["std"] } futures-util = { version = "0.3.17", default-features = false, features = ["std"] }
rand = "0.9" rand = "0.9"
rcgen = "0.13" rcgen = "0.13"
rustls-pemfile = "2" rustls-pki-types = "1.13.1"
serde = { version = "1", features = ["derive"] } serde = { version = "1", features = ["derive"] }
static_assertions = "1" static_assertions = "1"
tls-openssl = { package = "openssl", version = "0.10.55" } tls-openssl = { package = "openssl", version = "0.10.55" }

View File

@ -8,10 +8,10 @@
<!-- prettier-ignore-start --> <!-- prettier-ignore-start -->
[![crates.io](https://img.shields.io/crates/v/actix-web?label=latest)](https://crates.io/crates/actix-web) [![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.12.0)](https://docs.rs/actix-web/4.12.0) [![Documentation](https://docs.rs/actix-web/badge.svg?version=4.12.1)](https://docs.rs/actix-web/4.12.1)
![MSRV](https://img.shields.io/badge/rustc-1.72+-ab6000.svg) ![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) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-web.svg)
[![Dependency Status](https://deps.rs/crate/actix-web/4.12.0/status.svg)](https://deps.rs/crate/actix-web/4.12.0) [![Dependency Status](https://deps.rs/crate/actix-web/4.12.1/status.svg)](https://deps.rs/crate/actix-web/4.12.1)
<br /> <br />
[![CI](https://github.com/actix/actix-web/actions/workflows/ci.yml/badge.svg)](https://github.com/actix/actix-web/actions/workflows/ci.yml) [![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/graph/badge.svg?token=dSwOnp9QCv)](https://codecov.io/gh/actix/actix-web) [![codecov](https://codecov.io/gh/actix/actix-web/graph/badge.svg?token=dSwOnp9QCv)](https://codecov.io/gh/actix/actix-web)
@ -78,23 +78,23 @@ async fn main() -> std::io::Result<()> {
### More Examples ### More Examples
- [Hello World](https://github.com/actix/examples/tree/mainasics/hello-world) - [Hello World](https://github.com/actix/examples/tree/main/basics/hello-world)
- [Basic Setup](https://github.com/actix/examples/tree/mainasics/basics) - [Basic Setup](https://github.com/actix/examples/tree/main/basics/basics)
- [Application State](https://github.com/actix/examples/tree/mainasics/state) - [Application State](https://github.com/actix/examples/tree/main/basics/state)
- [JSON Handling](https://github.com/actix/examples/tree/mainson/json) - [JSON Handling](https://github.com/actix/examples/tree/main/json/json)
- [Multipart Streams](https://github.com/actix/examples/tree/mainorms/multipart) - [Multipart Streams](https://github.com/actix/examples/tree/main/forms/multipart)
- [MongoDB Integration](https://github.com/actix/examples/tree/mainatabases/mongodb) - [MongoDB Integration](https://github.com/actix/examples/tree/main/databases/mongodb)
- [Diesel Integration](https://github.com/actix/examples/tree/mainatabases/diesel) - [Diesel Integration](https://github.com/actix/examples/tree/main/databases/diesel)
- [SQLite Integration](https://github.com/actix/examples/tree/mainatabases/sqlite) - [SQLite Integration](https://github.com/actix/examples/tree/main/databases/sqlite)
- [Postgres Integration](https://github.com/actix/examples/tree/mainatabases/postgres) - [Postgres Integration](https://github.com/actix/examples/tree/main/databases/postgres)
- [Tera Templates](https://github.com/actix/examples/tree/mainemplating/tera) - [Tera Templates](https://github.com/actix/examples/tree/main/templating/tera)
- [Askama Templates](https://github.com/actix/examples/tree/mainemplating/askama) - [Askama Templates](https://github.com/actix/examples/tree/main/templating/askama)
- [HTTPS using Rustls](https://github.com/actix/examples/tree/mainttps-tls/rustls) - [HTTPS using Rustls](https://github.com/actix/examples/tree/main/https-tls/rustls)
- [HTTPS using OpenSSL](https://github.com/actix/examples/tree/mainttps-tls/openssl) - [HTTPS using OpenSSL](https://github.com/actix/examples/tree/main/https-tls/openssl)
- [Simple WebSocket](https://github.com/actix/examples/tree/mainebsockets) - [Simple WebSocket](https://github.com/actix/examples/tree/main/websockets)
- [WebSocket Chat](https://github.com/actix/examples/tree/mainebsockets/chat) - [WebSocket Chat](https://github.com/actix/examples/tree/main/websockets/chat)
You may consider checking out [this directory](https://github.com/actix/examples/tree/mainfor more examples. You may consider checking out [this directory](https://github.com/actix/examples/tree/main) for more examples.
## Benchmarks ## Benchmarks

View File

@ -688,30 +688,20 @@ async fn test_brotli_encoding_large_openssl() {
#[cfg(feature = "rustls-0_23")] #[cfg(feature = "rustls-0_23")]
mod plus_rustls { mod plus_rustls {
use std::io::BufReader;
use rustls::{pki_types::PrivateKeyDer, ServerConfig as RustlsServerConfig}; use rustls::{pki_types::PrivateKeyDer, ServerConfig as RustlsServerConfig};
use rustls_pemfile::{certs, pkcs8_private_keys}; use rustls_pki_types::PrivatePkcs8KeyDer;
use super::*; use super::*;
fn tls_config() -> RustlsServerConfig { fn tls_config() -> RustlsServerConfig {
let rcgen::CertifiedKey { cert, key_pair } = let rcgen::CertifiedKey { cert, key_pair } =
rcgen::generate_simple_self_signed(["localhost".to_owned()]).unwrap(); rcgen::generate_simple_self_signed(["localhost".to_owned()]).unwrap();
let cert_file = cert.pem(); let cert_chain = vec![cert.der().clone()];
let key_file = key_pair.serialize_pem(); let key_der = PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from(key_pair.serialize_der()));
let cert_file = &mut BufReader::new(cert_file.as_bytes());
let key_file = &mut BufReader::new(key_file.as_bytes());
let cert_chain = certs(cert_file).collect::<Result<Vec<_>, _>>().unwrap();
let mut keys = pkcs8_private_keys(key_file)
.collect::<Result<Vec<_>, _>>()
.unwrap();
RustlsServerConfig::builder() RustlsServerConfig::builder()
.with_no_client_auth() .with_no_client_auth()
.with_single_cert(cert_chain, PrivateKeyDer::Pkcs8(keys.remove(0))) .with_single_cert(cert_chain, key_der)
.unwrap() .unwrap()
} }

View File

@ -2,6 +2,8 @@
## Unreleased ## Unreleased
- Minimum supported Rust version (MSRV) is now 1.82.
## 3.8.1 ## 3.8.1
- Fix a bug where `GO_AWAY` errors did not stop connections from returning to the pool. - Fix a bug where `GO_AWAY` errors did not stop connections from returning to the pool.

View File

@ -149,7 +149,7 @@ flate2 = "1.0.13"
futures-util = { version = "0.3.17", default-features = false } futures-util = { version = "0.3.17", default-features = false }
static_assertions = "1.1" static_assertions = "1.1"
rcgen = "0.13" rcgen = "0.13"
rustls-pemfile = "2" rustls-pki-types = "1.13.1"
tokio = { version = "1.38.2", features = ["rt-multi-thread", "macros"] } tokio = { version = "1.38.2", features = ["rt-multi-thread", "macros"] }
zstd = "0.13" 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 tls-rustls-0_23 = { package = "rustls", version = "0.23" } # add rustls 0.23 with default features to make aws_lc_rs work in tests

View File

@ -309,10 +309,7 @@ impl ClientRequest {
/// Freeze request builder and construct `FrozenClientRequest`, /// Freeze request builder and construct `FrozenClientRequest`,
/// which could be used for sending same request multiple times. /// which could be used for sending same request multiple times.
pub fn freeze(self) -> Result<FrozenClientRequest, FreezeRequestError> { pub fn freeze(self) -> Result<FrozenClientRequest, FreezeRequestError> {
let slf = match self.prep_for_sending() { let slf = self.prep_for_sending()?;
Ok(slf) => slf,
Err(err) => return Err(err.into()),
};
let request = FrozenClientRequest { let request = FrozenClientRequest {
head: Rc::new(slf.head), head: Rc::new(slf.head),

View File

@ -2,12 +2,9 @@
extern crate tls_rustls_0_23 as rustls; extern crate tls_rustls_0_23 as rustls;
use std::{ use std::sync::{
io::BufReader, atomic::{AtomicUsize, Ordering},
sync::{ Arc,
atomic::{AtomicUsize, Ordering},
Arc,
},
}; };
use actix_http::HttpService; use actix_http::HttpService;
@ -16,29 +13,18 @@ use actix_service::{fn_service, map_config, ServiceFactoryExt};
use actix_tls::connect::rustls_0_23::webpki_roots_cert_store; use actix_tls::connect::rustls_0_23::webpki_roots_cert_store;
use actix_utils::future::ok; use actix_utils::future::ok;
use actix_web::{dev::AppConfig, http::Version, web, App, HttpResponse}; use actix_web::{dev::AppConfig, http::Version, web, App, HttpResponse};
use rustls::{ use rustls::{pki_types::ServerName, ClientConfig, ServerConfig};
pki_types::{CertificateDer, PrivateKeyDer, ServerName}, use rustls_pki_types::{CertificateDer, PrivateKeyDer, PrivatePkcs8KeyDer};
ClientConfig, ServerConfig,
};
use rustls_pemfile::{certs, pkcs8_private_keys};
fn tls_config() -> ServerConfig { fn tls_config() -> ServerConfig {
let rcgen::CertifiedKey { cert, key_pair } = let rcgen::CertifiedKey { cert, key_pair } =
rcgen::generate_simple_self_signed(["localhost".to_owned()]).unwrap(); rcgen::generate_simple_self_signed(["localhost".to_owned()]).unwrap();
let cert_file = cert.pem(); let cert_chain = vec![cert.der().clone()];
let key_file = key_pair.serialize_pem(); let key_der = PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from(key_pair.serialize_der()));
let cert_file = &mut BufReader::new(cert_file.as_bytes());
let key_file = &mut BufReader::new(key_file.as_bytes());
let cert_chain = certs(cert_file).collect::<Result<Vec<_>, _>>().unwrap();
let mut keys = pkcs8_private_keys(key_file)
.collect::<Result<Vec<_>, _>>()
.unwrap();
ServerConfig::builder() ServerConfig::builder()
.with_no_client_auth() .with_no_client_auth()
.with_single_cert(cert_chain, PrivateKeyDer::Pkcs8(keys.remove(0))) .with_single_cert(cert_chain, key_der)
.unwrap() .unwrap()
} }

View File

@ -12,14 +12,7 @@ fmt:
# Downgrade dependencies necessary to run MSRV checks/tests. # Downgrade dependencies necessary to run MSRV checks/tests.
[private] [private]
downgrade-for-msrv: downgrade-for-msrv:
cargo {{ toolchain }} update -p=divan --precise=0.1.15 # next ver: 1.80.0 # no downgrades currently needed
cargo {{ toolchain }} update -p=rayon --precise=1.10.0 # next ver: 1.80.0
cargo {{ toolchain }} update -p=rayon-core --precise=1.12.1 # next ver: 1.80.0
cargo {{ toolchain }} update -p=half --precise=2.4.1 # next ver: 1.81.0
cargo {{ toolchain }} update -p=idna_adapter --precise=1.2.0 # next ver: 1.82.0
cargo {{ toolchain }} update -p=litemap --precise=0.7.4 # next ver: 1.81.0
cargo {{ toolchain }} update -p=zerofrom --precise=0.1.5 # next ver: 1.81.0
cargo {{ toolchain }} update -p=time --precise=0.3.41 # next ver: 1.81.0
msrv := ``` msrv := ```
cargo metadata --format-version=1 \ cargo metadata --format-version=1 \