Merge branch 'master' into asonix/shutdown-when-not-reading-full-request

This commit is contained in:
asonix 2025-09-25 17:46:37 -05:00 committed by GitHub
commit f985a8dc3b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 574 additions and 289 deletions

View File

@ -2,12 +2,14 @@ version: "0.2"
words:
- actix
- addrs
- ALPN
- bytestring
- httparse
- msrv
- MSRV
- realip
- rustls
- rustup
- serde
- uring
- webpki
- zstd

View File

@ -44,12 +44,12 @@ jobs:
echo "RUSTFLAGS=-C target-feature=+crt-static" >> $GITHUB_ENV
- name: Install Rust (${{ matrix.version.name }})
uses: actions-rust-lang/setup-rust-toolchain@ac90e63697ac2784f4ecfe2964e1a285c304003a # v1.14.1
uses: actions-rust-lang/setup-rust-toolchain@2fcdc490d667999e01ddbbf0f2823181beef6b39 # v1.15.0
with:
toolchain: ${{ matrix.version.version }}
- name: Install just, cargo-hack, cargo-nextest, cargo-ci-cache-clean
uses: taiki-e/install-action@14083e64ac8cf1f5e54356df00b9779b23e192a1 # v2.58.29
uses: taiki-e/install-action@0e09747a63ae497bf945b3dcaf38fef0050d0109 # v2.62.0
with:
tool: just,cargo-hack,cargo-nextest,cargo-ci-cache-clean
@ -80,10 +80,10 @@ jobs:
uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1
- name: Install Rust
uses: actions-rust-lang/setup-rust-toolchain@ac90e63697ac2784f4ecfe2964e1a285c304003a # v1.14.1
uses: actions-rust-lang/setup-rust-toolchain@2fcdc490d667999e01ddbbf0f2823181beef6b39 # v1.15.0
- name: Install just, cargo-hack
uses: taiki-e/install-action@14083e64ac8cf1f5e54356df00b9779b23e192a1 # v2.58.29
uses: taiki-e/install-action@0e09747a63ae497bf945b3dcaf38fef0050d0109 # v2.62.0
with:
tool: just,cargo-hack

View File

@ -59,12 +59,12 @@ jobs:
uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1
- name: Install Rust (${{ matrix.version.name }})
uses: actions-rust-lang/setup-rust-toolchain@ac90e63697ac2784f4ecfe2964e1a285c304003a # v1.14.1
uses: actions-rust-lang/setup-rust-toolchain@2fcdc490d667999e01ddbbf0f2823181beef6b39 # v1.15.0
with:
toolchain: ${{ matrix.version.version }}
- name: Install just, cargo-hack, cargo-nextest, cargo-ci-cache-clean
uses: taiki-e/install-action@14083e64ac8cf1f5e54356df00b9779b23e192a1 # v2.58.29
uses: taiki-e/install-action@0e09747a63ae497bf945b3dcaf38fef0050d0109 # v2.62.0
with:
tool: just,cargo-hack,cargo-nextest,cargo-ci-cache-clean
@ -92,7 +92,7 @@ jobs:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- name: Install Rust
uses: actions-rust-lang/setup-rust-toolchain@ac90e63697ac2784f4ecfe2964e1a285c304003a # v1.14.1
uses: actions-rust-lang/setup-rust-toolchain@2fcdc490d667999e01ddbbf0f2823181beef6b39 # v1.15.0
with:
toolchain: nightly
@ -108,12 +108,12 @@ jobs:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- name: Install Rust (nightly)
uses: actions-rust-lang/setup-rust-toolchain@ac90e63697ac2784f4ecfe2964e1a285c304003a # v1.14.1
uses: actions-rust-lang/setup-rust-toolchain@2fcdc490d667999e01ddbbf0f2823181beef6b39 # v1.15.0
with:
toolchain: nightly
- name: Install just
uses: taiki-e/install-action@14083e64ac8cf1f5e54356df00b9779b23e192a1 # v2.58.29
uses: taiki-e/install-action@0e09747a63ae497bf945b3dcaf38fef0050d0109 # v2.62.0
with:
tool: just

View File

@ -18,13 +18,13 @@ jobs:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- name: Install Rust (nightly)
uses: actions-rust-lang/setup-rust-toolchain@ac90e63697ac2784f4ecfe2964e1a285c304003a # v1.14.1
uses: actions-rust-lang/setup-rust-toolchain@2fcdc490d667999e01ddbbf0f2823181beef6b39 # v1.15.0
with:
toolchain: nightly
components: llvm-tools
- name: Install just, cargo-llvm-cov, cargo-nextest
uses: taiki-e/install-action@14083e64ac8cf1f5e54356df00b9779b23e192a1 # v2.58.29
uses: taiki-e/install-action@0e09747a63ae497bf945b3dcaf38fef0050d0109 # v2.62.0
with:
tool: just,cargo-llvm-cov,cargo-nextest
@ -32,7 +32,7 @@ jobs:
run: just test-coverage-codecov
- name: Upload coverage to Codecov
uses: codecov/codecov-action@fdcc8476540edceab3de004e990f80d881c6cc00 # v5.5.0
uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # v5.5.1
with:
files: codecov.json
fail_ci_if_error: true

View File

@ -18,7 +18,7 @@ jobs:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- name: Install Rust (nightly)
uses: actions-rust-lang/setup-rust-toolchain@ac90e63697ac2784f4ecfe2964e1a285c304003a # v1.14.1
uses: actions-rust-lang/setup-rust-toolchain@2fcdc490d667999e01ddbbf0f2823181beef6b39 # v1.15.0
with:
toolchain: nightly
components: rustfmt
@ -36,7 +36,7 @@ jobs:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- name: Install Rust
uses: actions-rust-lang/setup-rust-toolchain@ac90e63697ac2784f4ecfe2964e1a285c304003a # v1.14.1
uses: actions-rust-lang/setup-rust-toolchain@2fcdc490d667999e01ddbbf0f2823181beef6b39 # v1.15.0
with:
components: clippy
@ -55,7 +55,7 @@ jobs:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- name: Install Rust (nightly)
uses: actions-rust-lang/setup-rust-toolchain@ac90e63697ac2784f4ecfe2964e1a285c304003a # v1.14.1
uses: actions-rust-lang/setup-rust-toolchain@2fcdc490d667999e01ddbbf0f2823181beef6b39 # v1.15.0
with:
toolchain: nightly
components: rust-docs
@ -72,12 +72,12 @@ jobs:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- name: Install Rust (${{ vars.RUST_VERSION_EXTERNAL_TYPES }})
uses: actions-rust-lang/setup-rust-toolchain@ac90e63697ac2784f4ecfe2964e1a285c304003a # v1.14.1
uses: actions-rust-lang/setup-rust-toolchain@2fcdc490d667999e01ddbbf0f2823181beef6b39 # v1.15.0
with:
toolchain: ${{ vars.RUST_VERSION_EXTERNAL_TYPES }}
- name: Install just
uses: taiki-e/install-action@14083e64ac8cf1f5e54356df00b9779b23e192a1 # v2.58.29
uses: taiki-e/install-action@0e09747a63ae497bf945b3dcaf38fef0050d0109 # v2.62.0
with:
tool: just

701
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -2,6 +2,11 @@
## Unreleased
## 0.6.8
- Add `Files::with_permanent_redirect()` method.
- Change default redirect status code to 307 Temporary Redirect.
## 0.6.7
- Add `{Files, NamedFile}::read_mode_threshold()` methods to allow faster synchronous reads of small files.

View File

@ -1,6 +1,6 @@
[package]
name = "actix-files"
version = "0.6.7"
version = "0.6.8"
authors = ["Nikolay Kim <fafhrd91@gmail.com>", "Rob Ede <robjtede@icloud.com>"]
description = "Static file serving for Actix Web"
keywords = ["actix", "http", "async", "futures"]

View File

@ -3,11 +3,11 @@
<!-- prettier-ignore-start -->
[![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.7)](https://docs.rs/actix-files/0.6.7)
[![Documentation](https://docs.rs/actix-files/badge.svg?version=0.6.8)](https://docs.rs/actix-files/0.6.8)
![Version](https://img.shields.io/badge/rustc-1.72+-ab6000.svg)
![License](https://img.shields.io/crates/l/actix-files.svg)
<br />
[![dependency status](https://deps.rs/crate/actix-files/0.6.7/status.svg)](https://deps.rs/crate/actix-files/0.6.7)
[![dependency status](https://deps.rs/crate/actix-files/0.6.8/status.svg)](https://deps.rs/crate/actix-files/0.6.8)
[![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)

View File

@ -41,6 +41,7 @@ pub struct Files {
index: Option<String>,
show_index: bool,
redirect_to_slash: bool,
with_permanent_redirect: bool,
default: Rc<RefCell<Option<Rc<HttpNewService>>>>,
renderer: Rc<DirectoryRenderer>,
mime_override: Option<Rc<MimeOverride>>,
@ -65,6 +66,7 @@ impl Clone for Files {
index: self.index.clone(),
show_index: self.show_index,
redirect_to_slash: self.redirect_to_slash,
with_permanent_redirect: self.with_permanent_redirect,
default: self.default.clone(),
renderer: self.renderer.clone(),
file_flags: self.file_flags,
@ -113,6 +115,7 @@ impl Files {
index: None,
show_index: false,
redirect_to_slash: false,
with_permanent_redirect: false,
default: Rc::new(RefCell::new(None)),
renderer: Rc::new(directory_listing),
mime_override: None,
@ -144,6 +147,14 @@ impl Files {
self
}
/// Redirect with permanent redirect status code (308).
///
/// By default redirect with temporary redirect status code (307).
pub fn with_permanent_redirect(mut self) -> Self {
self.with_permanent_redirect = true;
self
}
/// Set custom directory renderer.
pub fn files_listing_renderer<F>(mut self, f: F) -> Self
where
@ -388,6 +399,7 @@ impl ServiceFactory<ServiceRequest> for Files {
guards: self.use_guards.clone(),
hidden_files: self.hidden_files,
size_threshold: self.read_mode_threshold,
with_permanent_redirect: self.with_permanent_redirect,
};
if let Some(ref default) = *self.default.borrow() {

View File

@ -736,7 +736,21 @@ mod tests {
.await;
let req = TestRequest::with_uri("/tests").to_request();
let resp = test::call_service(&srv, req).await;
assert_eq!(resp.status(), StatusCode::FOUND);
assert_eq!(resp.status(), StatusCode::TEMPORARY_REDIRECT);
// should redirect if index present with permanent redirect
let srv = test::init_service(
App::new().service(
Files::new("/", ".")
.index_file("test.png")
.redirect_to_slash_directory()
.with_permanent_redirect(),
),
)
.await;
let req = TestRequest::with_uri("/tests").to_request();
let resp = test::call_service(&srv, req).await;
assert_eq!(resp.status(), StatusCode::PERMANENT_REDIRECT);
// should redirect if files listing is enabled
let srv = test::init_service(
@ -749,7 +763,7 @@ mod tests {
.await;
let req = TestRequest::with_uri("/tests").to_request();
let resp = test::call_service(&srv, req).await;
assert_eq!(resp.status(), StatusCode::FOUND);
assert_eq!(resp.status(), StatusCode::TEMPORARY_REDIRECT);
// should not redirect if the path is wrong
let req = TestRequest::with_uri("/not_existing").to_request();

View File

@ -40,6 +40,7 @@ pub struct FilesServiceInner {
pub(crate) guards: Option<Rc<dyn Guard>>,
pub(crate) hidden_files: bool,
pub(crate) size_threshold: u64,
pub(crate) with_permanent_redirect: bool,
}
impl fmt::Debug for FilesServiceInner {
@ -148,11 +149,15 @@ impl Service<ServiceRequest> for FilesService {
{
let redirect_to = format!("{}/", req.path());
return Ok(req.into_response(
HttpResponse::Found()
let response = if this.with_permanent_redirect {
HttpResponse::PermanentRedirect()
} else {
HttpResponse::TemporaryRedirect()
}
.insert_header((header::LOCATION, redirect_to))
.finish(),
));
.finish();
return Ok(req.into_response(response));
}
match this.index {

View File

@ -52,7 +52,6 @@ allowed_external_types = [
"serde_json::*",
"serde_urlencoded::*",
"serde::*",
"serde::*",
"tokio::*",
"url::*",
]

View File

@ -16,7 +16,6 @@ Middleware is registered for each App, Scope, or Resource and executed in the re
Actix Web's middleware system is built on two main traits:
1. `Transform<S, Req>`: The builder trait that creates the actual Service. It's responsible for:
- Creating new middleware instances
- Assembling the middleware chain
- Handling initialization errors

View File

@ -2,6 +2,11 @@
## Unreleased
## 3.8.0
- Add `hickory-dns` crate feature (off-by-default).
- The `trust-dns` crate feature now delegates DNS resolution to `hickory-dns`.
## 3.7.0
- Update `brotli` dependency to `8`.

View File

@ -1,6 +1,6 @@
[package]
name = "awc"
version = "3.7.0"
version = "3.8.0"
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
description = "Async HTTP and WebSocket client library"
keywords = ["actix", "http", "framework", "async", "web"]
@ -82,8 +82,10 @@ compress-zstd = ["actix-http/compress-zstd", "__compress"]
# Cookie parsing and cookie jar
cookies = ["dep:cookie"]
# Use `trust-dns-resolver` crate as DNS resolver
trust-dns = ["trust-dns-resolver"]
# Use `hickory-dns-resolver` crate as DNS resolver
hickory-dns = ["dep:hickory-resolver"]
# Use `trust-dns-resolver` crate as DNS resolver (deprecated, use `hickory-dns`)
trust-dns = ["hickory-dns"]
# Internal (PRIVATE!) features used to aid testing and checking feature status.
# Don't rely on these whatsoever. They may disappear at anytime.
@ -129,7 +131,7 @@ tls-rustls-0_21 = { package = "rustls", version = "0.21", optional = true, featu
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 }
hickory-resolver = { version = "0.25", optional = true, features = ["system-config", "tokio"] }
[dev-dependencies]
actix-http = { version = "3.7", features = ["openssl"] }

View File

@ -5,9 +5,9 @@
<!-- prettier-ignore-start -->
[![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.7.0)](https://docs.rs/awc/3.7.0)
[![Documentation](https://docs.rs/awc/badge.svg?version=3.8.0)](https://docs.rs/awc/3.8.0)
![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/awc)
[![Dependency Status](https://deps.rs/crate/awc/3.7.0/status.svg)](https://deps.rs/crate/awc/3.7.0)
[![Dependency Status](https://deps.rs/crate/awc/3.8.0/status.svg)](https://deps.rs/crate/awc/3.8.0)
[![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x)
<!-- prettier-ignore-end -->

View File

@ -1037,7 +1037,7 @@ where
}
}
#[cfg(not(feature = "trust-dns"))]
#[cfg(not(feature = "hickory-dns"))]
mod resolver {
use super::*;
@ -1046,24 +1046,25 @@ mod resolver {
}
}
#[cfg(feature = "trust-dns")]
#[cfg(feature = "hickory-dns")]
mod resolver {
use std::{cell::RefCell, net::SocketAddr};
use std::{cell::OnceCell, net::SocketAddr};
use actix_tls::connect::Resolve;
use trust_dns_resolver::{
use hickory_resolver::{
config::{ResolverConfig, ResolverOpts},
name_server::TokioConnectionProvider,
system_conf::read_system_conf,
TokioAsyncResolver,
TokioResolver,
};
use super::*;
pub(super) fn resolver() -> Resolver {
// new type for impl Resolve trait for TokioAsyncResolver.
struct TrustDnsResolver(TokioAsyncResolver);
struct HickoryDnsResolver(TokioResolver);
impl Resolve for TrustDnsResolver {
impl Resolve for HickoryDnsResolver {
fn lookup<'a>(
&'a self,
host: &'a str,
@ -1085,34 +1086,29 @@ mod resolver {
// resolver struct is cached in thread local so new clients can reuse the existing instance
thread_local! {
static TRUST_DNS_RESOLVER: RefCell<Option<Resolver>> = const { RefCell::new(None) };
static HICKORY_DNS_RESOLVER: OnceCell<Resolver> = const { OnceCell::new() };
}
// get from thread local or construct a new trust-dns resolver.
TRUST_DNS_RESOLVER.with(|local| {
let resolver = local.borrow().as_ref().map(Clone::clone);
match resolver {
Some(resolver) => resolver,
None => {
// get from thread local or construct a new hickory dns resolver.
HICKORY_DNS_RESOLVER.with(|local| {
local
.get_or_init(|| {
let (cfg, opts) = match read_system_conf() {
Ok((cfg, opts)) => (cfg, opts),
Err(err) => {
log::error!("Trust-DNS can not load system config: {err}");
log::error!("Hickory DNS can not load system config: {err}");
(ResolverConfig::default(), ResolverOpts::default())
}
};
let resolver = TokioAsyncResolver::tokio(cfg, opts);
let resolver =
TokioResolver::builder_with_config(cfg, TokioConnectionProvider::default())
.with_options(opts)
.build();
// box trust dns resolver and put it in thread local.
let resolver = Resolver::custom(TrustDnsResolver(resolver));
*local.borrow_mut() = Some(resolver.clone());
resolver
}
}
Resolver::custom(HickoryDnsResolver(resolver))
})
.clone()
})
}
}

View File

@ -19,6 +19,7 @@ downgrade-for-msrv:
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 := ```
cargo metadata --format-version=1 \