mirror of
https://github.com/servo/servo.git
synced 2025-07-16 03:43:38 +01:00
Net side of XHR fetch integration
This commit is contained in:
parent
b5255f011e
commit
2cbc8dee25
5 changed files with 107 additions and 6 deletions
|
@ -847,6 +847,7 @@ fn http_network_fetch(request: Rc<Request>,
|
|||
Ok((mut res, _)) => {
|
||||
response.url = Some(res.response.url.clone());
|
||||
response.status = Some(res.response.status);
|
||||
response.raw_status = Some(res.response.status_raw().clone());
|
||||
response.headers = res.response.headers.clone();
|
||||
|
||||
let res_body = response.body.clone();
|
||||
|
|
|
@ -11,6 +11,7 @@ use cookie;
|
|||
use cookie_storage::CookieStorage;
|
||||
use data_loader;
|
||||
use devtools_traits::DevtoolsControlMsg;
|
||||
use fetch::methods::fetch;
|
||||
use file_loader;
|
||||
use filemanager_thread::FileManagerThreadFactory;
|
||||
use hsts::HstsList;
|
||||
|
@ -23,8 +24,10 @@ use mime_classifier::{ApacheBugFlag, MIMEClassifier, NoSniffFlag};
|
|||
use net_traits::LoadContext;
|
||||
use net_traits::ProgressMsg::Done;
|
||||
use net_traits::{AsyncResponseTarget, Metadata, ProgressMsg, ResponseAction, CoreResourceThread};
|
||||
use net_traits::{CoreResourceMsg, CookieSource, LoadConsumer, LoadData, LoadResponse, ResourceId};
|
||||
use net_traits::{NetworkError, WebSocketCommunicate, WebSocketConnectData, ResourceThreads};
|
||||
use net_traits::{CoreResourceMsg, CookieSource, FetchResponseMsg, LoadConsumer};
|
||||
use net_traits::{LoadData, LoadResponse, NetworkError, ResourceId};
|
||||
use net_traits::{WebSocketCommunicate, WebSocketConnectData, ResourceThreads};
|
||||
use net_traits::request::{Referer, Request};
|
||||
use profile_traits::time::ProfilerChan;
|
||||
use rustc_serialize::json;
|
||||
use rustc_serialize::{Decodable, Encodable};
|
||||
|
@ -36,6 +39,7 @@ use std::error::Error;
|
|||
use std::fs::File;
|
||||
use std::io::prelude::*;
|
||||
use std::path::Path;
|
||||
use std::rc::Rc;
|
||||
use std::sync::mpsc::{Receiver, Sender, channel};
|
||||
use std::sync::{Arc, RwLock};
|
||||
use storage_thread::StorageThreadFactory;
|
||||
|
@ -193,6 +197,8 @@ impl ResourceChannelManager {
|
|||
match self.from_client.recv().unwrap() {
|
||||
CoreResourceMsg::Load(load_data, consumer, id_sender) =>
|
||||
self.resource_manager.load(load_data, consumer, id_sender, control_sender.clone()),
|
||||
CoreResourceMsg::Fetch(load_data, sender) =>
|
||||
self.resource_manager.fetch(load_data, sender),
|
||||
CoreResourceMsg::WebsocketConnect(connect, connect_data) =>
|
||||
self.resource_manager.websocket_connect(connect, connect_data),
|
||||
CoreResourceMsg::SetCookiesForUrl(request, cookie_list, source) =>
|
||||
|
@ -480,6 +486,35 @@ impl CoreResourceManager {
|
|||
cancel_listener));
|
||||
}
|
||||
|
||||
fn fetch(&self, load_data: LoadData, sender: IpcSender<FetchResponseMsg>) {
|
||||
spawn_named(format!("fetch thread for {}", load_data.url), move || {
|
||||
let mut request = Request::new(load_data.url,
|
||||
None, false);
|
||||
// todo handle origin
|
||||
// todo consider replacing LoadData with a direct mapping
|
||||
// to a subset of Request
|
||||
// todo set is_service_worker_global_scope
|
||||
*request.method.borrow_mut() = load_data.method;
|
||||
*request.headers.borrow_mut() = load_data.headers;
|
||||
*request.body.borrow_mut() = load_data.data.clone();
|
||||
if let Some(cors) = load_data.cors {
|
||||
request.use_cors_preflight = cors.preflight;
|
||||
}
|
||||
// XXXManishearth: Check origin against pipeline id
|
||||
request.use_url_credentials = load_data.credentials_flag;
|
||||
// todo load context / mimesniff in fetch
|
||||
// todo referrer policy?
|
||||
if let Some(referer) = load_data.referrer_url {
|
||||
request.referer = Referer::RefererUrl(referer);
|
||||
}
|
||||
// todo worker stuff
|
||||
|
||||
|
||||
fetch(Rc::new(request), Some(Box::new(sender)));
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
fn websocket_connect(&self,
|
||||
connect: WebSocketCommunicate,
|
||||
connect_data: WebSocketConnectData) {
|
||||
|
|
|
@ -112,6 +112,7 @@ pub struct LoadData {
|
|||
pub headers: Headers,
|
||||
#[ignore_heap_size_of = "Defined in hyper"]
|
||||
/// Headers that will apply to the initial request and any redirects
|
||||
/// Unused in fetch
|
||||
pub preserved_headers: Headers,
|
||||
pub data: Option<Vec<u8>>,
|
||||
pub cors: Option<ResourceCORSData>,
|
||||
|
@ -154,6 +155,16 @@ pub trait LoadOrigin {
|
|||
fn pipeline_id(&self) -> Option<PipelineId>;
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub enum FetchResponseMsg {
|
||||
// todo: should have fields for transmitted/total bytes
|
||||
ProcessRequestBody,
|
||||
ProcessRequestEOF,
|
||||
// todo: send more info about the response (or perhaps the entire Response)
|
||||
ProcessResponse(Result<Metadata, NetworkError>),
|
||||
ProcessResponseEOF(Result<Vec<u8>, NetworkError>),
|
||||
}
|
||||
|
||||
pub trait FetchTaskTarget {
|
||||
/// https://fetch.spec.whatwg.org/#process-request-body
|
||||
///
|
||||
|
@ -176,6 +187,36 @@ pub trait FetchTaskTarget {
|
|||
fn process_response_eof(&mut self, response: &response::Response);
|
||||
}
|
||||
|
||||
impl FetchTaskTarget for IpcSender<FetchResponseMsg> {
|
||||
fn process_request_body(&mut self, _: &request::Request) {
|
||||
let _ = self.send(FetchResponseMsg::ProcessRequestBody);
|
||||
}
|
||||
|
||||
fn process_request_eof(&mut self, _: &request::Request) {
|
||||
let _ = self.send(FetchResponseMsg::ProcessRequestEOF);
|
||||
}
|
||||
|
||||
fn process_response(&mut self, response: &response::Response) {
|
||||
let _ = self.send(FetchResponseMsg::ProcessResponse(response.metadata()));
|
||||
}
|
||||
|
||||
fn process_response_eof(&mut self, response: &response::Response) {
|
||||
if response.is_network_error() {
|
||||
// todo: finer grained errors
|
||||
let _ = self.send(FetchResponseMsg::ProcessResponse(Err(NetworkError::Internal("Network error".into()))));
|
||||
}
|
||||
if let Ok(ref guard) = response.body.lock() {
|
||||
if let response::ResponseBody::Done(ref vec) = **guard {
|
||||
let _ = self.send(FetchResponseMsg::ProcessResponseEOF(Ok(vec.clone())));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If something goes wrong, log it instead of crashing the resource thread
|
||||
let _ = self.send(FetchResponseMsg::ProcessResponseEOF(Err(NetworkError::Internal("Incomplete body".into()))));
|
||||
}
|
||||
}
|
||||
|
||||
/// A listener for asynchronous network events. Cancelling the underlying request is unsupported.
|
||||
pub trait AsyncResponseListener {
|
||||
/// The response headers for a request have been received.
|
||||
|
@ -348,6 +389,7 @@ pub struct WebSocketConnectData {
|
|||
pub enum CoreResourceMsg {
|
||||
/// Request the data associated with a particular URL
|
||||
Load(LoadData, LoadConsumer, Option<IpcSender<ResourceId>>),
|
||||
Fetch(LoadData, IpcSender<FetchResponseMsg>),
|
||||
/// Try to make a websocket connection to a URL.
|
||||
WebsocketConnect(WebSocketCommunicate, WebSocketConnectData),
|
||||
/// Store a set of cookies for a given originating URL
|
||||
|
|
|
@ -43,6 +43,7 @@ pub enum Origin {
|
|||
#[derive(Clone, PartialEq)]
|
||||
pub enum Referer {
|
||||
NoReferer,
|
||||
/// Default referer if nothing is specified
|
||||
Client,
|
||||
RefererUrl(Url)
|
||||
}
|
||||
|
|
|
@ -4,15 +4,17 @@
|
|||
|
||||
//! The [Response](https://fetch.spec.whatwg.org/#responses) object
|
||||
//! resulting from a [fetch operation](https://fetch.spec.whatwg.org/#concept-fetch)
|
||||
use hyper::header::{AccessControlExposeHeaders, Headers};
|
||||
use hyper::header::{AccessControlExposeHeaders, ContentType, Headers};
|
||||
use hyper::http::RawStatus;
|
||||
use hyper::status::StatusCode;
|
||||
use {Metadata, NetworkError};
|
||||
use std::ascii::AsciiExt;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use url::Url;
|
||||
|
||||
/// [Response type](https://fetch.spec.whatwg.org/#concept-response-type)
|
||||
#[derive(Clone, PartialEq, Copy, Debug)]
|
||||
#[derive(Clone, PartialEq, Copy, Debug, Deserialize, Serialize)]
|
||||
pub enum ResponseType {
|
||||
Basic,
|
||||
CORS,
|
||||
|
@ -23,7 +25,7 @@ pub enum ResponseType {
|
|||
}
|
||||
|
||||
/// [Response termination reason](https://fetch.spec.whatwg.org/#concept-response-termination-reason)
|
||||
#[derive(Clone, Copy)]
|
||||
#[derive(Clone, Copy, Deserialize, Serialize)]
|
||||
pub enum TerminationReason {
|
||||
EndUserAbort,
|
||||
Fatal,
|
||||
|
@ -50,7 +52,7 @@ impl ResponseBody {
|
|||
|
||||
|
||||
/// [Cache state](https://fetch.spec.whatwg.org/#concept-response-cache-state)
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub enum CacheState {
|
||||
None,
|
||||
Local,
|
||||
|
@ -81,6 +83,7 @@ pub struct Response {
|
|||
pub url_list: RefCell<Vec<Url>>,
|
||||
/// `None` can be considered a StatusCode of `0`.
|
||||
pub status: Option<StatusCode>,
|
||||
pub raw_status: Option<RawStatus>,
|
||||
pub headers: Headers,
|
||||
pub body: Arc<Mutex<ResponseBody>>,
|
||||
pub cache_state: CacheState,
|
||||
|
@ -100,6 +103,7 @@ impl Response {
|
|||
url: None,
|
||||
url_list: RefCell::new(Vec::new()),
|
||||
status: Some(StatusCode::Ok),
|
||||
raw_status: Some(RawStatus(200, "OK".into())),
|
||||
headers: Headers::new(),
|
||||
body: Arc::new(Mutex::new(ResponseBody::Empty)),
|
||||
cache_state: CacheState::None,
|
||||
|
@ -116,6 +120,7 @@ impl Response {
|
|||
url: None,
|
||||
url_list: RefCell::new(vec![]),
|
||||
status: None,
|
||||
raw_status: None,
|
||||
headers: Headers::new(),
|
||||
body: Arc::new(Mutex::new(ResponseBody::Empty)),
|
||||
cache_state: CacheState::None,
|
||||
|
@ -216,4 +221,21 @@ impl Response {
|
|||
|
||||
response
|
||||
}
|
||||
|
||||
pub fn metadata(&self) -> Result<Metadata, NetworkError> {
|
||||
let mut metadata = if let Some(ref url) = self.url {
|
||||
Metadata::default(url.clone())
|
||||
} else {
|
||||
return Err(NetworkError::Internal("No url found".to_string()));
|
||||
};
|
||||
|
||||
metadata.set_content_type(match self.headers.get() {
|
||||
Some(&ContentType(ref mime)) => Some(mime),
|
||||
None => None
|
||||
});
|
||||
metadata.headers = Some(self.headers.clone());
|
||||
metadata.status = self.raw_status.clone();
|
||||
metadata.https_state = self.https_state;
|
||||
return Ok(metadata);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue