mirror of
https://github.com/servo/servo.git
synced 2025-08-05 05:30:08 +01:00
Support for byte range requests on file urls
This commit is contained in:
parent
cc0ac89e1a
commit
0f73544297
1 changed files with 45 additions and 3 deletions
|
@ -10,6 +10,7 @@ use filemanager_thread::FileManager;
|
||||||
use http_loader::{HttpState, determine_request_referrer, http_fetch};
|
use http_loader::{HttpState, determine_request_referrer, http_fetch};
|
||||||
use http_loader::{set_default_accept, set_default_accept_language};
|
use http_loader::{set_default_accept, set_default_accept_language};
|
||||||
use hyper::{Error, Result as HyperResult};
|
use hyper::{Error, Result as HyperResult};
|
||||||
|
use hyper::header;
|
||||||
use hyper::header::{Accept, AcceptLanguage, AccessControlExposeHeaders, ContentLanguage, ContentType};
|
use hyper::header::{Accept, AcceptLanguage, AccessControlExposeHeaders, ContentLanguage, ContentType};
|
||||||
use hyper::header::{Header, HeaderFormat, HeaderView, Headers, Referer as RefererHeader};
|
use hyper::header::{Header, HeaderFormat, HeaderView, Headers, Referer as RefererHeader};
|
||||||
use hyper::method::Method;
|
use hyper::method::Method;
|
||||||
|
@ -26,7 +27,7 @@ use servo_url::ServoUrl;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{BufReader, BufRead};
|
use std::io::{BufReader, BufRead, Seek, SeekFrom};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::str;
|
use std::str;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
@ -502,8 +503,33 @@ fn scheme_fetch(request: &mut Request,
|
||||||
|
|
||||||
let cancellation_listener = context.cancellation_listener.clone();
|
let cancellation_listener = context.cancellation_listener.clone();
|
||||||
|
|
||||||
|
let range = request.headers.get::<header::Range>();
|
||||||
|
let (start, end) = if let Some(&header::Range::Bytes(ref range)) = range {
|
||||||
|
match range.first().unwrap() {
|
||||||
|
&header::ByteRangeSpec::AllFrom(start) => (start, None),
|
||||||
|
&header::ByteRangeSpec::FromTo(start, end) => {
|
||||||
|
// `end` should be less or equal to `start`.
|
||||||
|
(start, Some(u64::max(start, end)))
|
||||||
|
},
|
||||||
|
&header::ByteRangeSpec::Last(offset) => {
|
||||||
|
if let Ok(metadata) = file.metadata() {
|
||||||
|
// `offset` cannot be bigger than the file size.
|
||||||
|
(metadata.len() - u64::min(metadata.len(), offset), None)
|
||||||
|
} else {
|
||||||
|
(0, None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
(0, None)
|
||||||
|
};
|
||||||
|
|
||||||
thread::Builder::new().name("fetch file worker thread".to_string()).spawn(move || {
|
thread::Builder::new().name("fetch file worker thread".to_string()).spawn(move || {
|
||||||
let mut reader = BufReader::with_capacity(FILE_CHUNK_SIZE, file);
|
let mut reader = BufReader::with_capacity(FILE_CHUNK_SIZE, file);
|
||||||
|
if reader.seek(SeekFrom::Start(start)).is_err() {
|
||||||
|
warn!("Fetch - could not seek to {:?}", start);
|
||||||
|
}
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
if cancellation_listener.lock().unwrap().cancelled() {
|
if cancellation_listener.lock().unwrap().cancelled() {
|
||||||
*res_body.lock().unwrap() = ResponseBody::Done(vec![]);
|
*res_body.lock().unwrap() = ResponseBody::Done(vec![]);
|
||||||
|
@ -512,9 +538,25 @@ fn scheme_fetch(request: &mut Request,
|
||||||
}
|
}
|
||||||
let length = {
|
let length = {
|
||||||
let mut buffer = reader.fill_buf().unwrap().to_vec();
|
let mut buffer = reader.fill_buf().unwrap().to_vec();
|
||||||
let buffer_len = buffer.len();
|
let mut buffer_len = buffer.len();
|
||||||
if let ResponseBody::Receiving(ref mut body) = *res_body.lock().unwrap() {
|
if let ResponseBody::Receiving(ref mut body) = *res_body.lock().unwrap() {
|
||||||
body.extend_from_slice(&buffer);
|
let offset = usize::min({
|
||||||
|
if let Some(end) = end {
|
||||||
|
let remaining_bytes =
|
||||||
|
end as usize - start as usize - body.len();
|
||||||
|
if remaining_bytes <= FILE_CHUNK_SIZE {
|
||||||
|
// This is the last chunk so we set buffer len to 0 to break
|
||||||
|
// the reading loop.
|
||||||
|
buffer_len = 0;
|
||||||
|
remaining_bytes
|
||||||
|
} else {
|
||||||
|
FILE_CHUNK_SIZE
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
FILE_CHUNK_SIZE
|
||||||
|
}
|
||||||
|
}, buffer.len());
|
||||||
|
body.extend_from_slice(&buffer[0..offset]);
|
||||||
let _ = done_sender.send(Data::Payload(buffer));
|
let _ = done_sender.send(Data::Payload(buffer));
|
||||||
}
|
}
|
||||||
buffer_len
|
buffer_len
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue