Added logging around HTTP range handling
This commit is contained in:
parent
f77be4a1e1
commit
727f830988
1 changed files with 34 additions and 7 deletions
41
src/serve.rs
41
src/serve.rs
|
@ -1,5 +1,7 @@
|
||||||
use rocket;
|
use rocket;
|
||||||
use rocket::http::hyper::header::*;
|
use rocket::http::hyper::header::*;
|
||||||
|
use rocket::http::Status;
|
||||||
|
use rocket::Response;
|
||||||
use rocket::response::{self, Responder};
|
use rocket::response::{self, Responder};
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::convert::From;
|
use std::convert::From;
|
||||||
|
@ -7,6 +9,7 @@ use std::fs::File;
|
||||||
use std::io::{Read, Seek, SeekFrom};
|
use std::io::{Read, Seek, SeekFrom};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum PartialFileRange {
|
pub enum PartialFileRange {
|
||||||
AllFrom(u64),
|
AllFrom(u64),
|
||||||
FromTo(u64, u64),
|
FromTo(u64, u64),
|
||||||
|
@ -41,9 +44,27 @@ impl<'r, R: Responder<'r>> RangeResponder<R> {
|
||||||
RangeResponder { original }
|
RangeResponder { original }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ignore_range(self, request: &rocket::request::Request) -> response::Result<'r> {
|
fn ignore_range(self, request: &rocket::request::Request, file_length: Option<u64>) -> response::Result<'r> {
|
||||||
let mut response = self.original.respond_to(request)?;
|
let mut response = self.original.respond_to(request)?;
|
||||||
response.set_status(rocket::http::Status::RangeNotSatisfiable);
|
if let Some(content_length) = file_length {
|
||||||
|
response.set_header(ContentLength(content_length));
|
||||||
|
}
|
||||||
|
response.set_status(Status::Ok);
|
||||||
|
Ok(response)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reject_range(self, file_length: Option<u64>) -> response::Result<'r> {
|
||||||
|
let mut response = Response::build()
|
||||||
|
.status(Status::RangeNotSatisfiable)
|
||||||
|
.finalize();
|
||||||
|
if file_length.is_some() {
|
||||||
|
let content_range = ContentRange(ContentRangeSpec::Bytes {
|
||||||
|
range: None,
|
||||||
|
instance_length: file_length,
|
||||||
|
});
|
||||||
|
response.set_header(content_range);
|
||||||
|
}
|
||||||
|
response.set_status(Status::RangeNotSatisfiable);
|
||||||
Ok(response)
|
Ok(response)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,15 +100,22 @@ fn truncate_range(range: &PartialFileRange, file_length: &Option<u64>) -> Option
|
||||||
|
|
||||||
impl<'r> Responder<'r> for RangeResponder<File> {
|
impl<'r> Responder<'r> for RangeResponder<File> {
|
||||||
fn respond_to(mut self, request: &rocket::request::Request) -> response::Result<'r> {
|
fn respond_to(mut self, request: &rocket::request::Request) -> response::Result<'r> {
|
||||||
|
|
||||||
|
let metadata: Option<_> = self.original.metadata().ok();
|
||||||
|
let file_length: Option<u64> = metadata.map(|m| m.len());
|
||||||
|
|
||||||
let range_header = request.headers().get_one("Range");
|
let range_header = request.headers().get_one("Range");
|
||||||
let range_header = match range_header {
|
let range_header = match range_header {
|
||||||
None => return Ok(self.original.respond_to(request)?),
|
None => return self.ignore_range(request, file_length),
|
||||||
Some(h) => h,
|
Some(h) => h,
|
||||||
};
|
};
|
||||||
|
|
||||||
let vec_range = match Range::from_str(range_header) {
|
let vec_range = match Range::from_str(range_header) {
|
||||||
Ok(Range::Bytes(v)) => v,
|
Ok(Range::Bytes(v)) => v,
|
||||||
_ => return self.ignore_range(request),
|
_ => {
|
||||||
|
warn!("Ignoring range header that could not be parse {:?}, file length is {:?}", range_header, file_length);
|
||||||
|
return self.ignore_range(request, file_length);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let partial_file_range = match vec_range.into_iter().next() {
|
let partial_file_range = match vec_range.into_iter().next() {
|
||||||
|
@ -95,8 +123,6 @@ impl<'r> Responder<'r> for RangeResponder<File> {
|
||||||
Some(byte_range) => PartialFileRange::from(byte_range),
|
Some(byte_range) => PartialFileRange::from(byte_range),
|
||||||
};
|
};
|
||||||
|
|
||||||
let metadata: Option<_> = self.original.metadata().ok();
|
|
||||||
let file_length: Option<u64> = metadata.map(|m| m.len());
|
|
||||||
let range: Option<(u64, u64)> = truncate_range(&partial_file_range, &file_length);
|
let range: Option<(u64, u64)> = truncate_range(&partial_file_range, &file_length);
|
||||||
|
|
||||||
if let Some((from, to)) = range {
|
if let Some((from, to)) = range {
|
||||||
|
@ -118,7 +144,8 @@ impl<'r> Responder<'r> for RangeResponder<File> {
|
||||||
|
|
||||||
Ok(response)
|
Ok(response)
|
||||||
} else {
|
} else {
|
||||||
self.ignore_range(request)
|
warn!("Rejecting unsatisfiable range header {:?}, file length is {:?}", &partial_file_range, &file_length);
|
||||||
|
self.reject_range(file_length)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue