fix(files): handle `bytes=0-` nicely (#3914)

This commit is contained in:
Yuki Okushi 2026-02-10 06:40:29 +09:00 committed by GitHub
parent 32cb3b8361
commit 5548fadc7d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 28 additions and 1 deletions

View File

@ -3,6 +3,7 @@
## Unreleased
- Add `Files::try_compressed()` to support serving pre-compressed static files [#2615]
- Fix handling of `bytes=0-`
[#2615]: https://github.com/actix/actix-web/pull/2615

View File

@ -513,6 +513,30 @@ mod tests {
assert_eq!(content_range.to_str().unwrap(), "bytes */100");
}
#[actix_rt::test]
async fn test_named_file_range_header_from_zero_to_end_returns_partial_content() {
let srv = actix_test::start(|| App::new().service(Files::new("/", ".")));
let response = srv
.get("/tests/test.binary")
.insert_header((header::RANGE, "bytes=0-"))
.send()
.await
.unwrap();
assert_eq!(response.status(), StatusCode::PARTIAL_CONTENT);
let content_range = response.headers().get(header::CONTENT_RANGE).unwrap();
assert_eq!(content_range.to_str().unwrap(), "bytes 0-99/100");
let content_length = response.headers().get(header::CONTENT_LENGTH).unwrap();
assert_eq!(content_length.to_str().unwrap(), "100");
// Should be no transfer-encoding
let transfer_encoding = response.headers().get(header::TRANSFER_ENCODING);
assert!(transfer_encoding.is_none());
}
#[actix_rt::test]
async fn test_named_file_content_length_headers() {
let srv = actix_test::start(|| App::new().service(Files::new("/", ".")));

View File

@ -550,6 +550,7 @@ impl NamedFile {
let mut length = self.md.len();
let mut offset = 0;
let mut ranged_req = false;
// check for range header
if let Some(ranges) = req.headers().get(header::RANGE) {
@ -558,6 +559,7 @@ impl NamedFile {
.ok()
.and_then(|ranges| ranges.first().copied())
{
ranged_req = true;
length = range.length;
offset = range.start;
@ -606,7 +608,7 @@ impl NamedFile {
let reader = chunked::new_chunked_read(length, offset, self.file, self.read_mode_threshold);
if offset != 0 || length != self.md.len() {
if ranged_req {
res.status(StatusCode::PARTIAL_CONTENT);
}