follow-up some inconsistency

This commit is contained in:
Yuki Okushi 2026-02-07 20:41:17 +09:00
parent 6c5ef0fada
commit 87bb9811c3
3 changed files with 31 additions and 14 deletions

View File

@ -2,6 +2,10 @@
## Unreleased
- Add `Files::try_compressed()` to support serving pre-compressed static files [#2615]
[#2615]: https://github.com/actix/actix-web/pull/2615
## 0.6.10
### Security Notice
@ -51,13 +55,10 @@ We encourage updating your `actix-files` version as soon as possible.
## 0.6.3
- XHTML files now use `Content-Disposition: inline` instead of `attachment`. [#2903]
- Add `Files::try_compressed()` to support serving pre-compressed static files [#2615]
- Minimum supported Rust version (MSRV) is now 1.59 due to transitive `time` dependency.
- Update `tokio-uring` dependency to `0.4`.
[#2903]: https://github.com/actix/actix-web/pull/2903
[#2615]: https://github.com/actix/actix-web/pull/2615
## 0.6.2

View File

@ -100,6 +100,11 @@ impl FilesService {
header::CONTENT_ENCODING,
header::HeaderValue::from_static(header_value),
);
// Response representation varies by Accept-Encoding when serving pre-compressed assets.
res.headers_mut().append(
header::VARY,
header::HeaderValue::from_static("accept-encoding"),
);
}
ServiceResponse::new(req, res)
}
@ -168,6 +173,15 @@ impl Service<ServiceRequest> for FilesService {
// full file path
let path = this.directory.join(&path_on_disk);
// Try serving pre-compressed file even if the uncompressed file doesn't exist yet.
// Still handle directories (index/listing) through the normal branch below.
if this.try_compressed && !path.is_dir() {
if let Some((named_file, encoding)) = find_compressed(&req, &path).await {
return Ok(this.serve_named_file_with_encoding(req, named_file, encoding));
}
}
if let Err(err) = path.canonicalize() {
return this.handle_err(err, req).await;
}
@ -216,11 +230,6 @@ impl Service<ServiceRequest> for FilesService {
)),
}
} else {
if this.try_compressed {
if let Some((named_file, encoding)) = find_compressed(&req, &path).await {
return Ok(this.serve_named_file_with_encoding(req, named_file, encoding));
}
}
match NamedFile::open_async(&path).await {
Ok(named_file) => Ok(this.serve_named_file(req, named_file)),
Err(err) => this.handle_err(err, req).await,
@ -293,11 +302,9 @@ async fn find_compressed(
};
let mut compressed_path = original_path.to_owned();
let filename = match compressed_path.file_name().and_then(|name| name.to_str()) {
Some(filename) => filename.to_owned(),
None => return None,
};
compressed_path.set_file_name(filename + extension);
let mut filename = compressed_path.file_name()?.to_owned();
filename.push(extension);
compressed_path.set_file_name(filename);
match NamedFile::open_async(&compressed_path).await {
Ok(mut named_file) => {

View File

@ -60,13 +60,17 @@ async fn test_compression_encodings() {
res.headers().get(header::CONTENT_ENCODING),
Some(&HeaderValue::from_static("gzip")),
);
assert_eq!(
res.headers().get(header::VARY),
Some(&HeaderValue::from_static("accept-encoding")),
);
assert_eq!(res.into_body().size(), actix_web::body::BodySize::Sized(76),);
// Select the highest priority encoding
let mut req = TestRequest::with_uri("/utf8.txt").to_request();
req.headers_mut().insert(
header::ACCEPT_ENCODING,
header::HeaderValue::from_static("gz;q=0.6,br;q=0.8,*"),
header::HeaderValue::from_static("gzip;q=0.6,br;q=0.8,*"),
);
let res = test::call_service(&srv, req).await;
@ -79,6 +83,10 @@ async fn test_compression_encodings() {
res.headers().get(header::CONTENT_ENCODING),
Some(&HeaderValue::from_static("br")),
);
assert_eq!(
res.headers().get(header::VARY),
Some(&HeaderValue::from_static("accept-encoding")),
);
assert_eq!(res.into_body().size(), actix_web::body::BodySize::Sized(49),);
// Request encoding that doesn't exist on disk and fallback to no encoding
@ -142,6 +150,7 @@ async fn test_compression_encodings() {
assert_eq!(res.headers().get(header::CONTENT_ENCODING), None);
}
#[actix_web::test]
async fn partial_range_response_encoding() {
let srv = test::init_service(App::new().default_service(web::to(|| async {
NamedFile::open_async("./tests/test.binary").await.unwrap()