Partial response ranges are now parsed properly

This commit is contained in:
shockrah 2022-03-02 21:21:04 -08:00
parent db637c0889
commit b7a3410fc4
2 changed files with 66 additions and 0 deletions

View File

@ -9,6 +9,7 @@ mod category;
mod video; mod video;
mod thumbnail; mod thumbnail;
mod common; mod common;
mod partial;
#[cfg(feature = "admin")] #[cfg(feature = "admin")]
mod admin; mod admin;

65
api/src/partial.rs Normal file
View File

@ -0,0 +1,65 @@
use rocket::http::Status;
use rocket::request::{Outcome, Request, FromRequest};
// Only single byte ranges are supported right now
pub struct Range {
start: u32,
end: Option<u32>
}
#[derive(Debug)]
pub enum RangeError {
Invalid,
Malformed
}
#[rocket::async_trait]
impl<'r> FromRequest<'r> for Range {
type Error = RangeError;
async fn from_request(req: &'r Request<'_>) -> Outcome<Self, Self::Error> {
// No range basically just means get the whole file
let range_raw = req.headers().get_one("range");
if range_raw.is_none() {
return Outcome::Success(Self { start: 0, end: None })
}
let range_raw = range_raw.unwrap();
// First make sure that we only ever handle byte ranges
const PREFIX: &'static str = "bytes=";
if !range_raw.starts_with(PREFIX) {
return Outcome::Failure((Status::BadRequest, RangeError::Invalid))
}
// Next strip the 'bytes=' out and grab the only everything until either
// ',' <whitespace> <end-of-line>
// ! Strip the comma if its there so we end up with a slice that matches
// [0-9]+-[0-9]+
let range_raw = range_raw
.strip_prefix(PREFIX).unwrap();
if let Some(ranges) = range_raw.split_once('-') {
let start = ranges.0.parse::<u32>();
let end = ranges.1.parse::<u32>().ok();
println!("Range collected {:?} -> {:?}", start, end);
match (start, end) {
(Ok(start), Some(end)) => {
if end <= start {
println!("Start end range invalid {}->{}", start, end);
return Outcome::Failure((Status::BadRequest, RangeError::Malformed))
}
return Outcome::Success(Self {
start, end: Some(end)
})
}
(Ok(start), None) => {
return Outcome::Success(Self { start, end: None })
}
_ => Outcome::Failure((Status::BadRequest, RangeError::Invalid))
}
} else {
return Outcome::Failure((Status::BadRequest, RangeError::Invalid));
}
}
}