v0.35.1: performance, AGPL licensing and documentation overhaul
- Web Server reads static files inline; proxy middleware chain flattened - About window with license summary and project links; AGPL-3.0-or-later - Rewritten documentation: feature list, screenshots, performance guide - Fix false spikes in per-Vhost request-rate charts
This commit is contained in:
1 parent
d3b492874b
commit
eba9f89283
135 files changed
+1425
-1064
No files matched your search
Vendored
+9
-12
@@ -12,11 +12,11 @@ pub enum RangeSelection {
|
||||
}
|
||||
|
||||
pub fn request_range(method: &Method, headers: &HeaderMap) -> RangeSelection {
|
||||
let mut values = headers.get_all("range").iter();
|
||||
let mut values = headers.get_all(::http::header::RANGE).iter();
|
||||
let Some(value) = values.next() else {
|
||||
return RangeSelection::None;
|
||||
};
|
||||
if values.next().is_some() || headers.get_all("if-range").iter().count() > 1 {
|
||||
if values.next().is_some() || headers.get_all(::http::header::IF_RANGE).iter().count() > 1 {
|
||||
return RangeSelection::Unsupported;
|
||||
}
|
||||
if method != Method::GET {
|
||||
@@ -74,7 +74,7 @@ fn if_range_matches(headers: &HeaderMap, if_range: Option<&HeaderValue>) -> bool
|
||||
return false;
|
||||
}
|
||||
return headers
|
||||
.get("etag")
|
||||
.get(::http::header::ETAG)
|
||||
.and_then(|value| value.to_str().ok())
|
||||
.is_some_and(|etag| !etag.trim().starts_with("W/") && etag.trim() == candidate);
|
||||
}
|
||||
@@ -82,7 +82,7 @@ fn if_range_matches(headers: &HeaderMap, if_range: Option<&HeaderValue>) -> bool
|
||||
return false;
|
||||
};
|
||||
headers
|
||||
.get("last-modified")
|
||||
.get(::http::header::LAST_MODIFIED)
|
||||
.and_then(|value| value.to_str().ok())
|
||||
.and_then(|value| httpdate::parse_http_date(value).ok())
|
||||
.is_some_and(|modified| modified <= candidate_date)
|
||||
@@ -127,32 +127,29 @@ impl Hit {
|
||||
let full_len = self.body.len();
|
||||
self.response
|
||||
.headers_mut()
|
||||
.insert("accept-ranges", HeaderValue::from_static("bytes"));
|
||||
.insert(::http::header::ACCEPT_RANGES, HeaderValue::from_static("bytes"));
|
||||
self.response
|
||||
.extensions_mut()
|
||||
.insert(crate::compression::Skip);
|
||||
let Some((start, end)) = resolve_byte_range(range, full_len) else {
|
||||
*self.response.status_mut() = StatusCode::RANGE_NOT_SATISFIABLE;
|
||||
*self.response.body_mut() = Body::empty();
|
||||
self.response.headers_mut().insert(
|
||||
"content-range",
|
||||
self.response.headers_mut().insert(::http::header::CONTENT_RANGE,
|
||||
HeaderValue::from_str(&format!("bytes */{full_len}")).expect("generated range"),
|
||||
);
|
||||
self.response
|
||||
.headers_mut()
|
||||
.insert("content-length", HeaderValue::from_static("0"));
|
||||
.insert(::http::header::CONTENT_LENGTH, HeaderValue::from_static("0"));
|
||||
return self;
|
||||
};
|
||||
let slice = self.body.slice(start..=end);
|
||||
*self.response.status_mut() = StatusCode::PARTIAL_CONTENT;
|
||||
*self.response.body_mut() = Body::from(slice.clone());
|
||||
self.response.headers_mut().insert(
|
||||
"content-range",
|
||||
self.response.headers_mut().insert(::http::header::CONTENT_RANGE,
|
||||
HeaderValue::from_str(&format!("bytes {start}-{end}/{full_len}"))
|
||||
.expect("generated range"),
|
||||
);
|
||||
self.response.headers_mut().insert(
|
||||
"content-length",
|
||||
self.response.headers_mut().insert(::http::header::CONTENT_LENGTH,
|
||||
HeaderValue::from_str(&slice.len().to_string()).expect("generated length"),
|
||||
);
|
||||
self.body = slice;
|
||||
|
||||
Reference in new issue
Block a user