diff --git a/actix-files/CHANGES.md b/actix-files/CHANGES.md index 3cc5afb53..ef0b79ae4 100644 --- a/actix-files/CHANGES.md +++ b/actix-files/CHANGES.md @@ -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 diff --git a/actix-files/src/lib.rs b/actix-files/src/lib.rs index 5ea578c0d..bf5397ecf 100644 --- a/actix-files/src/lib.rs +++ b/actix-files/src/lib.rs @@ -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("/", "."))); diff --git a/actix-files/src/named.rs b/actix-files/src/named.rs index 77ae53d1c..1a3c2b3a1 100644 --- a/actix-files/src/named.rs +++ b/actix-files/src/named.rs @@ -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); }