aboutsummaryrefslogtreecommitdiff
path: root/src/modules/files.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules/files.rs')
-rw-r--r--src/modules/files.rs84
1 files changed, 45 insertions, 39 deletions
diff --git a/src/modules/files.rs b/src/modules/files.rs
index caee799..ab98f66 100644
--- a/src/modules/files.rs
+++ b/src/modules/files.rs
@@ -174,7 +174,7 @@ impl Node for Files {
// };
let range = request.headers().typed_get::<headers::Range>();
- let range = bytes_range(range, metadata.len())?;
+ let (range_satisfied, range) = bytes_range(range, metadata.len());
debug!("sending file {path:?}");
let file = File::open(path.clone()).await?;
@@ -190,15 +190,24 @@ impl Node for Files {
)))
};
- if !skip_body && range.end - range.start != metadata.len() {
- *r.status_mut() = StatusCode::PARTIAL_CONTENT;
- r.headers_mut().typed_insert(
- ContentRange::bytes(range.clone(), metadata.len()).expect("valid ContentRange"),
- );
- }
- // if not_modified || etag_matches {
- if not_modified {
+ if skip_body {
*r.status_mut() = StatusCode::NOT_MODIFIED;
+ } else {
+ if range_satisfied {
+ if range.end - range.start != metadata.len() {
+ *r.status_mut() = StatusCode::PARTIAL_CONTENT;
+ r.headers_mut().typed_insert(
+ ContentRange::bytes(range.clone(), metadata.len())
+ .expect("valid ContentRange"),
+ );
+ } else {
+ *r.status_mut() = StatusCode::OK;
+ }
+ } else {
+ *r.status_mut() = StatusCode::RANGE_NOT_SATISFIABLE;
+ r.headers_mut()
+ .typed_insert(ContentRange::unsatisfied_bytes(metadata.len()));
+ }
}
r.headers_mut().typed_insert(AcceptRanges::bytes());
@@ -284,46 +293,43 @@ fn file_stream(
}
// Also adapted from warp
-fn bytes_range(range: Option<headers::Range>, max_len: u64) -> Result<Range<u64>, ServiceError> {
+// Returns the a valid range and if the range request was satisfied.
+fn bytes_range(range: Option<headers::Range>, max_len: u64) -> (bool, Range<u64>) {
use std::ops::Bound;
let range = if let Some(range) = range {
range
} else {
- return Ok(0..max_len);
+ return (true, 0..max_len);
};
- let ret = range
- .satisfiable_ranges(max_len)
- .map(|(start, end)| {
- let start = match start {
- Bound::Unbounded => 0,
- Bound::Included(s) => s,
- Bound::Excluded(s) => s + 1,
- };
+ let sat = range.satisfiable_ranges(max_len).find_map(|(start, end)| {
+ let start = match start {
+ Bound::Unbounded => 0,
+ Bound::Included(s) => s,
+ Bound::Excluded(s) => s + 1,
+ };
- let end = match end {
- Bound::Unbounded => max_len,
- Bound::Included(s) => {
- // For the special case where s == the file size
- if s == max_len {
- s
- } else {
- s + 1
- }
+ let end = match end {
+ Bound::Unbounded => max_len,
+ Bound::Included(s) => {
+ // For the special case where s == the file size
+ if s == max_len {
+ s
+ } else {
+ s + 1
}
- Bound::Excluded(s) => s,
- };
-
- if start < end && end <= max_len {
- Ok(start..end)
- } else {
- Err(ServiceError::BadRange)
}
- })
- .next()
- .unwrap_or(Ok(0..max_len));
- ret
+ Bound::Excluded(s) => s,
+ };
+
+ if start < end && end <= max_len {
+ Some((true, start..end))
+ } else {
+ None
+ }
+ });
+ sat.unwrap_or((false, 0..max_len))
}
fn reserve_at_least(buf: &mut BytesMut, cap: usize) {