mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
Added devtools support to fetch for XHR + Manish's XHR ident fix
added unit test for request fetch with devtools added devtools/fetch test
This commit is contained in:
parent
45209b7ffe
commit
db808ca75d
9 changed files with 213 additions and 74 deletions
|
@ -43,6 +43,7 @@ pub struct NetworkEventActor {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
request: HttpRequest,
|
request: HttpRequest,
|
||||||
response: HttpResponse,
|
response: HttpResponse,
|
||||||
|
is_xhr: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
|
@ -340,7 +341,8 @@ impl NetworkEventActor {
|
||||||
headers: None,
|
headers: None,
|
||||||
status: None,
|
status: None,
|
||||||
body: None,
|
body: None,
|
||||||
}
|
},
|
||||||
|
is_xhr: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -353,6 +355,7 @@ impl NetworkEventActor {
|
||||||
self.request.timeStamp = request.timeStamp;
|
self.request.timeStamp = request.timeStamp;
|
||||||
self.request.connect_time = request.connect_time;
|
self.request.connect_time = request.connect_time;
|
||||||
self.request.send_time = request.send_time;
|
self.request.send_time = request.send_time;
|
||||||
|
self.is_xhr = request.is_xhr;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_response(&mut self, response: DevtoolsHttpResponse) {
|
pub fn add_response(&mut self, response: DevtoolsHttpResponse) {
|
||||||
|
@ -369,7 +372,7 @@ impl NetworkEventActor {
|
||||||
method: format!("{}", self.request.method),
|
method: format!("{}", self.request.method),
|
||||||
startedDateTime: format!("{}", self.request.startedDateTime.rfc3339()),
|
startedDateTime: format!("{}", self.request.startedDateTime.rfc3339()),
|
||||||
timeStamp: self.request.timeStamp,
|
timeStamp: self.request.timeStamp,
|
||||||
isXHR: false,
|
isXHR: self.is_xhr,
|
||||||
private: false,
|
private: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -298,6 +298,7 @@ pub struct HttpRequest {
|
||||||
pub timeStamp: i64,
|
pub timeStamp: i64,
|
||||||
pub connect_time: u64,
|
pub connect_time: u64,
|
||||||
pub send_time: u64,
|
pub send_time: u64,
|
||||||
|
pub is_xhr: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
|
|
|
@ -4,10 +4,12 @@
|
||||||
|
|
||||||
use connector::create_http_connector;
|
use connector::create_http_connector;
|
||||||
use data_loader::decode;
|
use data_loader::decode;
|
||||||
|
use devtools_traits::DevtoolsControlMsg;
|
||||||
use fetch::cors_cache::CORSCache;
|
use fetch::cors_cache::CORSCache;
|
||||||
use http_loader::{HttpState, set_default_accept_encoding, set_request_cookies};
|
use http_loader::{HttpState, set_default_accept_encoding, set_request_cookies};
|
||||||
use http_loader::{NetworkHttpRequestFactory, ReadResult, StreamedResponse, obtain_response, read_block};
|
use http_loader::{NetworkHttpRequestFactory, ReadResult, StreamedResponse, obtain_response, read_block};
|
||||||
use http_loader::{auth_from_cache, determine_request_referrer};
|
use http_loader::{auth_from_cache, determine_request_referrer};
|
||||||
|
use http_loader::{send_response_to_devtools, send_request_to_devtools};
|
||||||
use hyper::header::{Accept, AcceptLanguage, Authorization, AccessControlAllowCredentials};
|
use hyper::header::{Accept, AcceptLanguage, Authorization, AccessControlAllowCredentials};
|
||||||
use hyper::header::{AccessControlAllowOrigin, AccessControlAllowHeaders, AccessControlAllowMethods};
|
use hyper::header::{AccessControlAllowOrigin, AccessControlAllowHeaders, AccessControlAllowMethods};
|
||||||
use hyper::header::{AccessControlRequestHeaders, AccessControlMaxAge, AccessControlRequestMethod, Basic};
|
use hyper::header::{AccessControlRequestHeaders, AccessControlMaxAge, AccessControlRequestMethod, Basic};
|
||||||
|
@ -20,7 +22,7 @@ use hyper::status::StatusCode;
|
||||||
use mime_guess::guess_mime_type;
|
use mime_guess::guess_mime_type;
|
||||||
use msg::constellation_msg::ReferrerPolicy;
|
use msg::constellation_msg::ReferrerPolicy;
|
||||||
use net_traits::FetchTaskTarget;
|
use net_traits::FetchTaskTarget;
|
||||||
use net_traits::request::{CacheMode, CredentialsMode};
|
use net_traits::request::{CacheMode, CredentialsMode, Destination};
|
||||||
use net_traits::request::{RedirectMode, Referer, Request, RequestMode, ResponseTainting};
|
use net_traits::request::{RedirectMode, Referer, Request, RequestMode, ResponseTainting};
|
||||||
use net_traits::request::{Type, Origin, Window};
|
use net_traits::request::{Type, Origin, Window};
|
||||||
use net_traits::response::{HttpsState, TerminationReason};
|
use net_traits::response::{HttpsState, TerminationReason};
|
||||||
|
@ -36,6 +38,7 @@ use std::sync::mpsc::{channel, Sender, Receiver};
|
||||||
use unicase::UniCase;
|
use unicase::UniCase;
|
||||||
use url::{Origin as UrlOrigin, Url};
|
use url::{Origin as UrlOrigin, Url};
|
||||||
use util::thread::spawn_named;
|
use util::thread::spawn_named;
|
||||||
|
use uuid;
|
||||||
|
|
||||||
pub type Target = Option<Box<FetchTaskTarget + Send>>;
|
pub type Target = Option<Box<FetchTaskTarget + Send>>;
|
||||||
|
|
||||||
|
@ -47,6 +50,7 @@ enum Data {
|
||||||
pub struct FetchContext {
|
pub struct FetchContext {
|
||||||
pub state: HttpState,
|
pub state: HttpState,
|
||||||
pub user_agent: String,
|
pub user_agent: String,
|
||||||
|
pub devtools_chan: Option<Sender<DevtoolsControlMsg>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
type DoneChannel = Option<(Sender<Data>, Receiver<Data>)>;
|
type DoneChannel = Option<(Sender<Data>, Receiver<Data>)>;
|
||||||
|
@ -210,7 +214,8 @@ fn main_fetch(request: Rc<Request>, cache: &mut CORSCache, cors_flag: bool,
|
||||||
request.headers.borrow().iter().any(|h| !is_simple_header(&h)))) {
|
request.headers.borrow().iter().any(|h| !is_simple_header(&h)))) {
|
||||||
request.response_tainting.set(ResponseTainting::CORSTainting);
|
request.response_tainting.set(ResponseTainting::CORSTainting);
|
||||||
request.redirect_mode.set(RedirectMode::Error);
|
request.redirect_mode.set(RedirectMode::Error);
|
||||||
let response = http_fetch(request.clone(), cache, true, true, false, target, done_chan, context);
|
let response = http_fetch(request.clone(), cache, true, true, false,
|
||||||
|
target, done_chan, context);
|
||||||
if response.is_network_error() {
|
if response.is_network_error() {
|
||||||
// TODO clear cache entries using request
|
// TODO clear cache entries using request
|
||||||
}
|
}
|
||||||
|
@ -888,7 +893,8 @@ fn http_network_or_cache_fetch(request: Rc<Request>,
|
||||||
|
|
||||||
// Step 18
|
// Step 18
|
||||||
if response.is_none() {
|
if response.is_none() {
|
||||||
response = Some(http_network_fetch(http_request.clone(), credentials_flag, done_chan));
|
response = Some(http_network_fetch(http_request.clone(), credentials_flag,
|
||||||
|
done_chan, context.devtools_chan.clone()));
|
||||||
}
|
}
|
||||||
let response = response.unwrap();
|
let response = response.unwrap();
|
||||||
|
|
||||||
|
@ -924,7 +930,8 @@ fn http_network_or_cache_fetch(request: Rc<Request>,
|
||||||
/// [HTTP network fetch](https://fetch.spec.whatwg.org/#http-network-fetch)
|
/// [HTTP network fetch](https://fetch.spec.whatwg.org/#http-network-fetch)
|
||||||
fn http_network_fetch(request: Rc<Request>,
|
fn http_network_fetch(request: Rc<Request>,
|
||||||
_credentials_flag: bool,
|
_credentials_flag: bool,
|
||||||
done_chan: &mut DoneChannel) -> Response {
|
done_chan: &mut DoneChannel,
|
||||||
|
devtools_chan: Option<Sender<DevtoolsControlMsg>>) -> Response {
|
||||||
// TODO: Implement HTTP network fetch spec
|
// TODO: Implement HTTP network fetch spec
|
||||||
|
|
||||||
// Step 1
|
// Step 1
|
||||||
|
@ -944,14 +951,22 @@ fn http_network_fetch(request: Rc<Request>,
|
||||||
let url = request.current_url();
|
let url = request.current_url();
|
||||||
let cancellation_listener = CancellationListener::new(None);
|
let cancellation_listener = CancellationListener::new(None);
|
||||||
|
|
||||||
|
let request_id = uuid::Uuid::new_v4().simple().to_string();
|
||||||
|
|
||||||
|
// XHR uses the default destination; other kinds of fetches (which haven't been implemented yet)
|
||||||
|
// do not. Once we support other kinds of fetches we'll need to be more fine grained here
|
||||||
|
// since things like image fetches are classified differently by devtools
|
||||||
|
let is_xhr = request.destination == Destination::None;
|
||||||
let wrapped_response = obtain_response(&factory, &url, &request.method.borrow(),
|
let wrapped_response = obtain_response(&factory, &url, &request.method.borrow(),
|
||||||
&request.headers.borrow(),
|
&request.headers.borrow(),
|
||||||
&cancellation_listener, &request.body.borrow(), &request.method.borrow(),
|
&cancellation_listener, &request.body.borrow(), &request.method.borrow(),
|
||||||
&None, request.redirect_count.get() + 1, &None, "");
|
&request.pipeline_id.get(), request.redirect_count.get() + 1,
|
||||||
|
&devtools_chan, &request_id, is_xhr);
|
||||||
|
|
||||||
|
let pipeline_id = request.pipeline_id.get();
|
||||||
let mut response = Response::new();
|
let mut response = Response::new();
|
||||||
match wrapped_response {
|
match wrapped_response {
|
||||||
Ok((res, _)) => {
|
Ok((res, msg)) => {
|
||||||
response.url = Some(url.clone());
|
response.url = Some(url.clone());
|
||||||
response.status = Some(res.response.status);
|
response.status = Some(res.response.status);
|
||||||
response.raw_status = Some(res.response.status_raw().clone());
|
response.raw_status = Some(res.response.status_raw().clone());
|
||||||
|
@ -963,10 +978,29 @@ fn http_network_fetch(request: Rc<Request>,
|
||||||
*done_chan = Some(channel());
|
*done_chan = Some(channel());
|
||||||
let meta = response.metadata().expect("Response metadata should exist at this stage");
|
let meta = response.metadata().expect("Response metadata should exist at this stage");
|
||||||
let done_sender = done_chan.as_ref().map(|ch| ch.0.clone());
|
let done_sender = done_chan.as_ref().map(|ch| ch.0.clone());
|
||||||
|
let devtools_sender = devtools_chan.clone();
|
||||||
|
let meta_status = meta.status.clone();
|
||||||
|
let meta_headers = meta.headers.clone();
|
||||||
spawn_named(format!("fetch worker thread"), move || {
|
spawn_named(format!("fetch worker thread"), move || {
|
||||||
match StreamedResponse::from_http_response(box res, meta) {
|
match StreamedResponse::from_http_response(box res, meta) {
|
||||||
Ok(mut res) => {
|
Ok(mut res) => {
|
||||||
*res_body.lock().unwrap() = ResponseBody::Receiving(vec![]);
|
*res_body.lock().unwrap() = ResponseBody::Receiving(vec![]);
|
||||||
|
|
||||||
|
if let Some(ref sender) = devtools_sender {
|
||||||
|
if let Some(m) = msg {
|
||||||
|
send_request_to_devtools(m, &sender);
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Tell devtools that we got a response
|
||||||
|
// Send an HttpResponse message to devtools with the corresponding request_id
|
||||||
|
if let Some(pipeline_id) = pipeline_id {
|
||||||
|
send_response_to_devtools(
|
||||||
|
&sender, request_id.into(),
|
||||||
|
meta_headers, meta_status,
|
||||||
|
pipeline_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
match read_block(&mut res) {
|
match read_block(&mut res) {
|
||||||
Ok(ReadResult::Payload(chunk)) => {
|
Ok(ReadResult::Payload(chunk)) => {
|
||||||
|
@ -994,7 +1028,6 @@ fn http_network_fetch(request: Rc<Request>,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
|
@ -1064,9 +1097,11 @@ fn http_network_fetch(request: Rc<Request>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// [CORS preflight fetch](https://fetch.spec.whatwg.org#cors-preflight-fetch)
|
/// [CORS preflight fetch](https://fetch.spec.whatwg.org#cors-preflight-fetch)
|
||||||
fn cors_preflight_fetch(request: Rc<Request>, cache: &mut CORSCache, context: &FetchContext) -> Response {
|
fn cors_preflight_fetch(request: Rc<Request>, cache: &mut CORSCache,
|
||||||
|
context: &FetchContext) -> Response {
|
||||||
// Step 1
|
// Step 1
|
||||||
let mut preflight = Request::new(request.current_url(), Some(request.origin.borrow().clone()), false);
|
let mut preflight = Request::new(request.current_url(), Some(request.origin.borrow().clone()),
|
||||||
|
false, request.pipeline_id.get());
|
||||||
*preflight.method.borrow_mut() = Method::Options;
|
*preflight.method.borrow_mut() = Method::Options;
|
||||||
preflight.initiator = request.initiator.clone();
|
preflight.initiator = request.initiator.clone();
|
||||||
preflight.type_ = request.type_.clone();
|
preflight.type_ = request.type_.clone();
|
||||||
|
|
|
@ -600,7 +600,8 @@ fn prepare_devtools_request(request_id: String,
|
||||||
pipeline_id: PipelineId,
|
pipeline_id: PipelineId,
|
||||||
now: Tm,
|
now: Tm,
|
||||||
connect_time: u64,
|
connect_time: u64,
|
||||||
send_time: u64) -> ChromeToDevtoolsControlMsg {
|
send_time: u64,
|
||||||
|
is_xhr: bool) -> ChromeToDevtoolsControlMsg {
|
||||||
let request = DevtoolsHttpRequest {
|
let request = DevtoolsHttpRequest {
|
||||||
url: url,
|
url: url,
|
||||||
method: method,
|
method: method,
|
||||||
|
@ -611,18 +612,19 @@ fn prepare_devtools_request(request_id: String,
|
||||||
timeStamp: now.to_timespec().sec,
|
timeStamp: now.to_timespec().sec,
|
||||||
connect_time: connect_time,
|
connect_time: connect_time,
|
||||||
send_time: send_time,
|
send_time: send_time,
|
||||||
|
is_xhr: is_xhr,
|
||||||
};
|
};
|
||||||
let net_event = NetworkEvent::HttpRequest(request);
|
let net_event = NetworkEvent::HttpRequest(request);
|
||||||
|
|
||||||
ChromeToDevtoolsControlMsg::NetworkEvent(request_id, net_event)
|
ChromeToDevtoolsControlMsg::NetworkEvent(request_id, net_event)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn send_request_to_devtools(msg: ChromeToDevtoolsControlMsg,
|
pub fn send_request_to_devtools(msg: ChromeToDevtoolsControlMsg,
|
||||||
devtools_chan: &Sender<DevtoolsControlMsg>) {
|
devtools_chan: &Sender<DevtoolsControlMsg>) {
|
||||||
devtools_chan.send(DevtoolsControlMsg::FromChrome(msg)).unwrap();
|
devtools_chan.send(DevtoolsControlMsg::FromChrome(msg)).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn send_response_to_devtools(devtools_chan: &Sender<DevtoolsControlMsg>,
|
pub fn send_response_to_devtools(devtools_chan: &Sender<DevtoolsControlMsg>,
|
||||||
request_id: String,
|
request_id: String,
|
||||||
headers: Option<Headers>,
|
headers: Option<Headers>,
|
||||||
status: Option<RawStatus>,
|
status: Option<RawStatus>,
|
||||||
|
@ -742,7 +744,8 @@ pub fn obtain_response<A>(request_factory: &HttpRequestFactory<R=A>,
|
||||||
pipeline_id: &Option<PipelineId>,
|
pipeline_id: &Option<PipelineId>,
|
||||||
iters: u32,
|
iters: u32,
|
||||||
devtools_chan: &Option<Sender<DevtoolsControlMsg>>,
|
devtools_chan: &Option<Sender<DevtoolsControlMsg>>,
|
||||||
request_id: &str)
|
request_id: &str,
|
||||||
|
is_xhr: bool)
|
||||||
-> Result<(A::R, Option<ChromeToDevtoolsControlMsg>), LoadError>
|
-> Result<(A::R, Option<ChromeToDevtoolsControlMsg>), LoadError>
|
||||||
where A: HttpRequest + 'static {
|
where A: HttpRequest + 'static {
|
||||||
let null_data = None;
|
let null_data = None;
|
||||||
|
@ -750,6 +753,7 @@ pub fn obtain_response<A>(request_factory: &HttpRequestFactory<R=A>,
|
||||||
let connection_url = replace_hosts(&url);
|
let connection_url = replace_hosts(&url);
|
||||||
let mut msg;
|
let mut msg;
|
||||||
|
|
||||||
|
|
||||||
// loop trying connections in connection pool
|
// loop trying connections in connection pool
|
||||||
// they may have grown stale (disconnected), in which case we'll get
|
// they may have grown stale (disconnected), in which case we'll get
|
||||||
// a ConnectionAborted error. this loop tries again with a new
|
// a ConnectionAborted error. this loop tries again with a new
|
||||||
|
@ -809,7 +813,7 @@ pub fn obtain_response<A>(request_factory: &HttpRequestFactory<R=A>,
|
||||||
request_id.clone().into(),
|
request_id.clone().into(),
|
||||||
url.clone(), method.clone(), headers,
|
url.clone(), method.clone(), headers,
|
||||||
request_body.clone(), pipeline_id, time::now(),
|
request_body.clone(), pipeline_id, time::now(),
|
||||||
connect_end - connect_start, send_end - send_start))
|
connect_end - connect_start, send_end - send_start, is_xhr))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -987,7 +991,7 @@ pub fn load<A, B>(load_data: &LoadData,
|
||||||
let (response, msg) =
|
let (response, msg) =
|
||||||
try!(obtain_response(request_factory, &doc_url, &method, &request_headers,
|
try!(obtain_response(request_factory, &doc_url, &method, &request_headers,
|
||||||
&cancel_listener, &load_data.data, &load_data.method,
|
&cancel_listener, &load_data.data, &load_data.method,
|
||||||
&load_data.pipeline_id, iters, &devtools_chan, &request_id));
|
&load_data.pipeline_id, iters, &devtools_chan, &request_id, false));
|
||||||
|
|
||||||
process_response_headers(&response, &doc_url, &http_state.cookie_jar, &http_state.hsts_list, &load_data);
|
process_response_headers(&response, &doc_url, &http_state.cookie_jar, &http_state.hsts_list, &load_data);
|
||||||
|
|
||||||
|
@ -1087,7 +1091,7 @@ pub fn load<A, B>(load_data: &LoadData,
|
||||||
if let Some(pipeline_id) = load_data.pipeline_id {
|
if let Some(pipeline_id) = load_data.pipeline_id {
|
||||||
if let Some(ref chan) = devtools_chan {
|
if let Some(ref chan) = devtools_chan {
|
||||||
send_response_to_devtools(
|
send_response_to_devtools(
|
||||||
chan, request_id,
|
&chan, request_id,
|
||||||
metadata.headers.clone(), metadata.status.clone(),
|
metadata.headers.clone(), metadata.status.clone(),
|
||||||
pipeline_id);
|
pipeline_id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -574,7 +574,7 @@ impl CoreResourceManager {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
debug!("resource_thread: loading url: {}", load_data.url);
|
debug!("loading url: {}", load_data.url);
|
||||||
|
|
||||||
loader.call_box((load_data,
|
loader.call_box((load_data,
|
||||||
consumer,
|
consumer,
|
||||||
|
@ -593,6 +593,7 @@ impl CoreResourceManager {
|
||||||
blocked_content: BLOCKED_CONTENT_RULES.clone(),
|
blocked_content: BLOCKED_CONTENT_RULES.clone(),
|
||||||
};
|
};
|
||||||
let ua = self.user_agent.clone();
|
let ua = self.user_agent.clone();
|
||||||
|
let dc = self.devtools_chan.clone();
|
||||||
spawn_named(format!("fetch thread for {}", init.url), move || {
|
spawn_named(format!("fetch thread for {}", init.url), move || {
|
||||||
let request = Request::from_init(init);
|
let request = Request::from_init(init);
|
||||||
// XXXManishearth: Check origin against pipeline id (also ensure that the mode is allowed)
|
// XXXManishearth: Check origin against pipeline id (also ensure that the mode is allowed)
|
||||||
|
@ -600,7 +601,7 @@ impl CoreResourceManager {
|
||||||
// todo referrer policy?
|
// todo referrer policy?
|
||||||
// todo service worker stuff
|
// todo service worker stuff
|
||||||
let mut target = Some(Box::new(sender) as Box<FetchTaskTarget + Send + 'static>);
|
let mut target = Some(Box::new(sender) as Box<FetchTaskTarget + Send + 'static>);
|
||||||
let context = FetchContext { state: http_state, user_agent: ua };
|
let context = FetchContext { state: http_state, user_agent: ua, devtools_chan: dc };
|
||||||
fetch(Rc::new(request), &mut target, context);
|
fetch(Rc::new(request), &mut target, context);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
use hyper::header::Headers;
|
use hyper::header::Headers;
|
||||||
use hyper::method::Method;
|
use hyper::method::Method;
|
||||||
use msg::constellation_msg::ReferrerPolicy;
|
use msg::constellation_msg::{PipelineId, ReferrerPolicy};
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell};
|
||||||
use std::mem::swap;
|
use std::mem::swap;
|
||||||
use url::{Origin as UrlOrigin, Url};
|
use url::{Origin as UrlOrigin, Url};
|
||||||
|
@ -130,6 +130,7 @@ pub struct RequestInit {
|
||||||
// XXXManishearth these should be part of the client object
|
// XXXManishearth these should be part of the client object
|
||||||
pub referer_url: Option<Url>,
|
pub referer_url: Option<Url>,
|
||||||
pub referrer_policy: Option<ReferrerPolicy>,
|
pub referrer_policy: Option<ReferrerPolicy>,
|
||||||
|
pub pipeline_id: Option<PipelineId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A [Request](https://fetch.spec.whatwg.org/#requests) as defined by the Fetch spec
|
/// A [Request](https://fetch.spec.whatwg.org/#requests) as defined by the Fetch spec
|
||||||
|
@ -159,6 +160,7 @@ pub struct Request {
|
||||||
/// https://fetch.spec.whatwg.org/#concept-request-referrer
|
/// https://fetch.spec.whatwg.org/#concept-request-referrer
|
||||||
pub referer: RefCell<Referer>,
|
pub referer: RefCell<Referer>,
|
||||||
pub referrer_policy: Cell<Option<ReferrerPolicy>>,
|
pub referrer_policy: Cell<Option<ReferrerPolicy>>,
|
||||||
|
pub pipeline_id: Cell<Option<PipelineId>>,
|
||||||
pub synchronous: bool,
|
pub synchronous: bool,
|
||||||
pub mode: RequestMode,
|
pub mode: RequestMode,
|
||||||
pub use_cors_preflight: bool,
|
pub use_cors_preflight: bool,
|
||||||
|
@ -178,7 +180,8 @@ pub struct Request {
|
||||||
impl Request {
|
impl Request {
|
||||||
pub fn new(url: Url,
|
pub fn new(url: Url,
|
||||||
origin: Option<Origin>,
|
origin: Option<Origin>,
|
||||||
is_service_worker_global_scope: bool) -> Request {
|
is_service_worker_global_scope: bool,
|
||||||
|
pipeline_id: Option<PipelineId>) -> Request {
|
||||||
Request {
|
Request {
|
||||||
method: RefCell::new(Method::Get),
|
method: RefCell::new(Method::Get),
|
||||||
local_urls_only: false,
|
local_urls_only: false,
|
||||||
|
@ -198,6 +201,7 @@ impl Request {
|
||||||
same_origin_data: Cell::new(false),
|
same_origin_data: Cell::new(false),
|
||||||
referer: RefCell::new(Referer::Client),
|
referer: RefCell::new(Referer::Client),
|
||||||
referrer_policy: Cell::new(None),
|
referrer_policy: Cell::new(None),
|
||||||
|
pipeline_id: Cell::new(pipeline_id),
|
||||||
synchronous: false,
|
synchronous: false,
|
||||||
mode: RequestMode::NoCORS,
|
mode: RequestMode::NoCORS,
|
||||||
use_cors_preflight: false,
|
use_cors_preflight: false,
|
||||||
|
@ -216,7 +220,7 @@ impl Request {
|
||||||
pub fn from_init(init: RequestInit) -> Request {
|
pub fn from_init(init: RequestInit) -> Request {
|
||||||
let mut req = Request::new(init.url,
|
let mut req = Request::new(init.url,
|
||||||
Some(Origin::Origin(init.origin.origin())),
|
Some(Origin::Origin(init.origin.origin())),
|
||||||
false);
|
false, init.pipeline_id);
|
||||||
*req.method.borrow_mut() = init.method;
|
*req.method.borrow_mut() = init.method;
|
||||||
*req.headers.borrow_mut() = init.headers;
|
*req.headers.borrow_mut() = init.headers;
|
||||||
req.unsafe_request = init.unsafe_request;
|
req.unsafe_request = init.unsafe_request;
|
||||||
|
@ -234,6 +238,7 @@ impl Request {
|
||||||
Referer::NoReferer
|
Referer::NoReferer
|
||||||
};
|
};
|
||||||
req.referrer_policy.set(init.referrer_policy);
|
req.referrer_policy.set(init.referrer_policy);
|
||||||
|
req.pipeline_id.set(init.pipeline_id);
|
||||||
req
|
req
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,7 +246,8 @@ impl Request {
|
||||||
pub fn potential_cors_request(url: Url,
|
pub fn potential_cors_request(url: Url,
|
||||||
cors_attribute_state: Option<CORSSettings>,
|
cors_attribute_state: Option<CORSSettings>,
|
||||||
is_service_worker_global_scope: bool,
|
is_service_worker_global_scope: bool,
|
||||||
same_origin_fallback: bool) -> Request {
|
same_origin_fallback: bool,
|
||||||
|
pipeline_id: Option<PipelineId>) -> Request {
|
||||||
Request {
|
Request {
|
||||||
method: RefCell::new(Method::Get),
|
method: RefCell::new(Method::Get),
|
||||||
local_urls_only: false,
|
local_urls_only: false,
|
||||||
|
@ -281,6 +287,7 @@ impl Request {
|
||||||
url_list: RefCell::new(vec![url]),
|
url_list: RefCell::new(vec![url]),
|
||||||
redirect_count: Cell::new(0),
|
redirect_count: Cell::new(0),
|
||||||
response_tainting: Cell::new(ResponseTainting::Basic),
|
response_tainting: Cell::new(ResponseTainting::Basic),
|
||||||
|
pipeline_id: Cell::new(pipeline_id),
|
||||||
done: Cell::new(false)
|
done: Cell::new(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -594,6 +594,7 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
|
||||||
origin: self.global().r().get_url(),
|
origin: self.global().r().get_url(),
|
||||||
referer_url: self.referrer_url.clone(),
|
referer_url: self.referrer_url.clone(),
|
||||||
referrer_policy: self.referrer_policy.clone(),
|
referrer_policy: self.referrer_policy.clone(),
|
||||||
|
pipeline_id: self.pipeline_id(),
|
||||||
};
|
};
|
||||||
|
|
||||||
if bypass_cross_origin_check {
|
if bypass_cross_origin_check {
|
||||||
|
|
|
@ -2,23 +2,31 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use hyper::header::{AccessControlAllowCredentials, AccessControlAllowHeaders, AccessControlAllowOrigin};
|
use devtools_traits::DevtoolsControlMsg;
|
||||||
use hyper::header::{AccessControlAllowMethods, AccessControlMaxAge};
|
use devtools_traits::HttpRequest as DevtoolsHttpRequest;
|
||||||
use hyper::header::{AccessControlRequestHeaders, AccessControlRequestMethod};
|
use devtools_traits::HttpResponse as DevtoolsHttpResponse;
|
||||||
use hyper::header::{CacheControl, ContentLanguage, ContentType, Expires, LastModified};
|
use http_loader::{expect_devtools_http_request, expect_devtools_http_response};
|
||||||
use hyper::header::{Headers, HttpDate, Location, SetCookie, Pragma};
|
use hyper::LanguageTag;
|
||||||
|
use hyper::header::{Accept, AccessControlAllowCredentials, AccessControlAllowHeaders, AccessControlAllowOrigin};
|
||||||
|
use hyper::header::{AccessControlAllowMethods, AccessControlMaxAge, AcceptLanguage, AcceptEncoding};
|
||||||
|
use hyper::header::{AccessControlRequestHeaders, AccessControlRequestMethod, UserAgent, Date};
|
||||||
|
use hyper::header::{CacheControl, ContentLanguage, ContentLength, ContentType, Expires, LastModified};
|
||||||
|
use hyper::header::{Headers, HttpDate, Host, Location, SetCookie, Pragma, Encoding, qitem};
|
||||||
|
use hyper::http::RawStatus;
|
||||||
use hyper::method::Method;
|
use hyper::method::Method;
|
||||||
use hyper::mime::{Mime, TopLevel, SubLevel};
|
use hyper::mime::{Mime, TopLevel, SubLevel};
|
||||||
use hyper::server::{Handler, Listening, Server};
|
use hyper::server::{Handler, Listening, Server};
|
||||||
use hyper::server::{Request as HyperRequest, Response as HyperResponse};
|
use hyper::server::{Request as HyperRequest, Response as HyperResponse};
|
||||||
use hyper::status::StatusCode;
|
use hyper::status::StatusCode;
|
||||||
use hyper::uri::RequestUri;
|
use hyper::uri::RequestUri;
|
||||||
|
use msg::constellation_msg::PipelineId;
|
||||||
use net::fetch::cors_cache::CORSCache;
|
use net::fetch::cors_cache::CORSCache;
|
||||||
use net::fetch::methods::{FetchContext, fetch, fetch_with_cors_cache};
|
use net::fetch::methods::{FetchContext, fetch, fetch_with_cors_cache};
|
||||||
use net::http_loader::HttpState;
|
use net::http_loader::HttpState;
|
||||||
use net_traits::FetchTaskTarget;
|
use net_traits::FetchTaskTarget;
|
||||||
use net_traits::request::{Origin, RedirectMode, Referer, Request, RequestMode};
|
use net_traits::request::{Origin, RedirectMode, Referer, Request, RequestMode};
|
||||||
use net_traits::response::{CacheState, Response, ResponseBody, ResponseType};
|
use net_traits::response::{CacheState, Response, ResponseBody, ResponseType};
|
||||||
|
use std::borrow::Cow;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
@ -31,16 +39,19 @@ use unicase::UniCase;
|
||||||
use url::{Origin as UrlOrigin, Url};
|
use url::{Origin as UrlOrigin, Url};
|
||||||
use util::resource_files::resources_dir_path;
|
use util::resource_files::resources_dir_path;
|
||||||
|
|
||||||
|
const DEFAULT_USER_AGENT: &'static str = "Such Browser. Very Layout. Wow.";
|
||||||
|
|
||||||
// TODO write a struct that impls Handler for storing test values
|
// TODO write a struct that impls Handler for storing test values
|
||||||
|
|
||||||
struct FetchResponseCollector {
|
struct FetchResponseCollector {
|
||||||
sender: Sender<Response>,
|
sender: Sender<Response>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_fetch_context() -> FetchContext {
|
fn new_fetch_context(dc: Option<Sender<DevtoolsControlMsg>>) -> FetchContext {
|
||||||
FetchContext {
|
FetchContext {
|
||||||
state: HttpState::new(),
|
state: HttpState::new(),
|
||||||
user_agent: "Such Browser. Very Layout. Wow.".into(),
|
user_agent: DEFAULT_USER_AGENT.into(),
|
||||||
|
devtools_chan: dc,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl FetchTaskTarget for FetchResponseCollector {
|
impl FetchTaskTarget for FetchResponseCollector {
|
||||||
|
@ -54,14 +65,14 @@ impl FetchTaskTarget for FetchResponseCollector {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fetch_async(request: Request, target: Box<FetchTaskTarget + Send>) {
|
fn fetch_async(request: Request, target: Box<FetchTaskTarget + Send>, dc: Option<Sender<DevtoolsControlMsg>>) {
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
fetch(Rc::new(request), &mut Some(target), new_fetch_context());
|
fetch(Rc::new(request), &mut Some(target), new_fetch_context(dc));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fetch_sync(request: Request) -> Response {
|
fn fetch_sync(request: Request, dc: Option<Sender<DevtoolsControlMsg>>) -> Response {
|
||||||
fetch(Rc::new(request), &mut None, new_fetch_context())
|
fetch(Rc::new(request), &mut None, new_fetch_context(dc))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_server<H: Handler + 'static>(handler: H) -> (Listening, Url) {
|
fn make_server<H: Handler + 'static>(handler: H) -> (Listening, Url) {
|
||||||
|
@ -83,9 +94,9 @@ fn test_fetch_response_is_not_network_error() {
|
||||||
let (mut server, url) = make_server(handler);
|
let (mut server, url) = make_server(handler);
|
||||||
|
|
||||||
let origin = Origin::Origin(url.origin());
|
let origin = Origin::Origin(url.origin());
|
||||||
let request = Request::new(url, Some(origin), false);
|
let request = Request::new(url, Some(origin), false, None);
|
||||||
*request.referer.borrow_mut() = Referer::NoReferer;
|
*request.referer.borrow_mut() = Referer::NoReferer;
|
||||||
let fetch_response = fetch_sync(request);
|
let fetch_response = fetch_sync(request, None);
|
||||||
let _ = server.close();
|
let _ = server.close();
|
||||||
|
|
||||||
if fetch_response.is_network_error() {
|
if fetch_response.is_network_error() {
|
||||||
|
@ -102,9 +113,9 @@ fn test_fetch_response_body_matches_const_message() {
|
||||||
let (mut server, url) = make_server(handler);
|
let (mut server, url) = make_server(handler);
|
||||||
|
|
||||||
let origin = Origin::Origin(url.origin());
|
let origin = Origin::Origin(url.origin());
|
||||||
let request = Request::new(url, Some(origin), false);
|
let request = Request::new(url, Some(origin), false, None);
|
||||||
*request.referer.borrow_mut() = Referer::NoReferer;
|
*request.referer.borrow_mut() = Referer::NoReferer;
|
||||||
let fetch_response = fetch_sync(request);
|
let fetch_response = fetch_sync(request, None);
|
||||||
let _ = server.close();
|
let _ = server.close();
|
||||||
|
|
||||||
assert!(!fetch_response.is_network_error());
|
assert!(!fetch_response.is_network_error());
|
||||||
|
@ -122,9 +133,9 @@ fn test_fetch_response_body_matches_const_message() {
|
||||||
fn test_fetch_aboutblank() {
|
fn test_fetch_aboutblank() {
|
||||||
let url = Url::parse("about:blank").unwrap();
|
let url = Url::parse("about:blank").unwrap();
|
||||||
let origin = Origin::Origin(url.origin());
|
let origin = Origin::Origin(url.origin());
|
||||||
let request = Request::new(url, Some(origin), false);
|
let request = Request::new(url, Some(origin), false, None);
|
||||||
*request.referer.borrow_mut() = Referer::NoReferer;
|
*request.referer.borrow_mut() = Referer::NoReferer;
|
||||||
let fetch_response = fetch_sync(request);
|
let fetch_response = fetch_sync(request, None);
|
||||||
assert!(!fetch_response.is_network_error());
|
assert!(!fetch_response.is_network_error());
|
||||||
assert!(*fetch_response.body.lock().unwrap() == ResponseBody::Done(vec![]));
|
assert!(*fetch_response.body.lock().unwrap() == ResponseBody::Done(vec![]));
|
||||||
}
|
}
|
||||||
|
@ -133,10 +144,10 @@ fn test_fetch_aboutblank() {
|
||||||
fn test_fetch_data() {
|
fn test_fetch_data() {
|
||||||
let url = Url::parse("data:text/html,<p>Servo</p>").unwrap();
|
let url = Url::parse("data:text/html,<p>Servo</p>").unwrap();
|
||||||
let origin = Origin::Origin(url.origin());
|
let origin = Origin::Origin(url.origin());
|
||||||
let request = Request::new(url, Some(origin), false);
|
let request = Request::new(url, Some(origin), false, None);
|
||||||
request.same_origin_data.set(true);
|
request.same_origin_data.set(true);
|
||||||
let expected_resp_body = "<p>Servo</p>".to_owned();
|
let expected_resp_body = "<p>Servo</p>".to_owned();
|
||||||
let fetch_response = fetch_sync(request);
|
let fetch_response = fetch_sync(request, None);
|
||||||
|
|
||||||
assert!(!fetch_response.is_network_error());
|
assert!(!fetch_response.is_network_error());
|
||||||
assert_eq!(fetch_response.headers.len(), 1);
|
assert_eq!(fetch_response.headers.len(), 1);
|
||||||
|
@ -162,10 +173,10 @@ fn test_fetch_file() {
|
||||||
|
|
||||||
let url = Url::from_file_path(path.clone()).unwrap();
|
let url = Url::from_file_path(path.clone()).unwrap();
|
||||||
let origin = Origin::Origin(url.origin());
|
let origin = Origin::Origin(url.origin());
|
||||||
let request = Request::new(url, Some(origin), false);
|
let request = Request::new(url, Some(origin), false, None);
|
||||||
request.same_origin_data.set(true);
|
request.same_origin_data.set(true);
|
||||||
|
|
||||||
let fetch_response = fetch_sync(request);
|
let fetch_response = fetch_sync(request, None);
|
||||||
assert!(!fetch_response.is_network_error());
|
assert!(!fetch_response.is_network_error());
|
||||||
assert_eq!(fetch_response.headers.len(), 1);
|
assert_eq!(fetch_response.headers.len(), 1);
|
||||||
let content_type: &ContentType = fetch_response.headers.get().unwrap();
|
let content_type: &ContentType = fetch_response.headers.get().unwrap();
|
||||||
|
@ -203,11 +214,11 @@ fn test_cors_preflight_fetch() {
|
||||||
let (mut server, url) = make_server(handler);
|
let (mut server, url) = make_server(handler);
|
||||||
|
|
||||||
let origin = Origin::Origin(UrlOrigin::new_opaque());
|
let origin = Origin::Origin(UrlOrigin::new_opaque());
|
||||||
let mut request = Request::new(url, Some(origin), false);
|
let mut request = Request::new(url, Some(origin), false, None);
|
||||||
*request.referer.borrow_mut() = Referer::NoReferer;
|
*request.referer.borrow_mut() = Referer::NoReferer;
|
||||||
request.use_cors_preflight = true;
|
request.use_cors_preflight = true;
|
||||||
request.mode = RequestMode::CORSMode;
|
request.mode = RequestMode::CORSMode;
|
||||||
let fetch_response = fetch_sync(request);
|
let fetch_response = fetch_sync(request, None);
|
||||||
let _ = server.close();
|
let _ = server.close();
|
||||||
|
|
||||||
assert!(!fetch_response.is_network_error());
|
assert!(!fetch_response.is_network_error());
|
||||||
|
@ -240,15 +251,17 @@ fn test_cors_preflight_cache_fetch() {
|
||||||
let (mut server, url) = make_server(handler);
|
let (mut server, url) = make_server(handler);
|
||||||
|
|
||||||
let origin = Origin::Origin(UrlOrigin::new_opaque());
|
let origin = Origin::Origin(UrlOrigin::new_opaque());
|
||||||
let mut request = Request::new(url.clone(), Some(origin.clone()), false);
|
let mut request = Request::new(url.clone(), Some(origin.clone()), false, None);
|
||||||
*request.referer.borrow_mut() = Referer::NoReferer;
|
*request.referer.borrow_mut() = Referer::NoReferer;
|
||||||
request.use_cors_preflight = true;
|
request.use_cors_preflight = true;
|
||||||
request.mode = RequestMode::CORSMode;
|
request.mode = RequestMode::CORSMode;
|
||||||
let wrapped_request0 = Rc::new(request.clone());
|
let wrapped_request0 = Rc::new(request.clone());
|
||||||
let wrapped_request1 = Rc::new(request);
|
let wrapped_request1 = Rc::new(request);
|
||||||
|
|
||||||
let fetch_response0 = fetch_with_cors_cache(wrapped_request0.clone(), &mut cache, &mut None, new_fetch_context());
|
let fetch_response0 = fetch_with_cors_cache(wrapped_request0.clone(), &mut cache,
|
||||||
let fetch_response1 = fetch_with_cors_cache(wrapped_request1.clone(), &mut cache, &mut None, new_fetch_context());
|
&mut None, new_fetch_context(None));
|
||||||
|
let fetch_response1 = fetch_with_cors_cache(wrapped_request1.clone(), &mut cache,
|
||||||
|
&mut None, new_fetch_context(None));
|
||||||
let _ = server.close();
|
let _ = server.close();
|
||||||
|
|
||||||
assert!(!fetch_response0.is_network_error() && !fetch_response1.is_network_error());
|
assert!(!fetch_response0.is_network_error() && !fetch_response1.is_network_error());
|
||||||
|
@ -289,12 +302,12 @@ fn test_cors_preflight_fetch_network_error() {
|
||||||
let (mut server, url) = make_server(handler);
|
let (mut server, url) = make_server(handler);
|
||||||
|
|
||||||
let origin = Origin::Origin(UrlOrigin::new_opaque());
|
let origin = Origin::Origin(UrlOrigin::new_opaque());
|
||||||
let mut request = Request::new(url, Some(origin), false);
|
let mut request = Request::new(url, Some(origin), false, None);
|
||||||
*request.method.borrow_mut() = Method::Extension("CHICKEN".to_owned());
|
*request.method.borrow_mut() = Method::Extension("CHICKEN".to_owned());
|
||||||
*request.referer.borrow_mut() = Referer::NoReferer;
|
*request.referer.borrow_mut() = Referer::NoReferer;
|
||||||
request.use_cors_preflight = true;
|
request.use_cors_preflight = true;
|
||||||
request.mode = RequestMode::CORSMode;
|
request.mode = RequestMode::CORSMode;
|
||||||
let fetch_response = fetch_sync(request);
|
let fetch_response = fetch_sync(request, None);
|
||||||
let _ = server.close();
|
let _ = server.close();
|
||||||
|
|
||||||
assert!(fetch_response.is_network_error());
|
assert!(fetch_response.is_network_error());
|
||||||
|
@ -313,9 +326,9 @@ fn test_fetch_response_is_basic_filtered() {
|
||||||
let (mut server, url) = make_server(handler);
|
let (mut server, url) = make_server(handler);
|
||||||
|
|
||||||
let origin = Origin::Origin(url.origin());
|
let origin = Origin::Origin(url.origin());
|
||||||
let request = Request::new(url, Some(origin), false);
|
let request = Request::new(url, Some(origin), false, None);
|
||||||
*request.referer.borrow_mut() = Referer::NoReferer;
|
*request.referer.borrow_mut() = Referer::NoReferer;
|
||||||
let fetch_response = fetch_sync(request);
|
let fetch_response = fetch_sync(request, None);
|
||||||
let _ = server.close();
|
let _ = server.close();
|
||||||
|
|
||||||
assert!(!fetch_response.is_network_error());
|
assert!(!fetch_response.is_network_error());
|
||||||
|
@ -358,10 +371,10 @@ fn test_fetch_response_is_cors_filtered() {
|
||||||
|
|
||||||
// an origin mis-match will stop it from defaulting to a basic filtered response
|
// an origin mis-match will stop it from defaulting to a basic filtered response
|
||||||
let origin = Origin::Origin(UrlOrigin::new_opaque());
|
let origin = Origin::Origin(UrlOrigin::new_opaque());
|
||||||
let mut request = Request::new(url, Some(origin), false);
|
let mut request = Request::new(url, Some(origin), false, None);
|
||||||
*request.referer.borrow_mut() = Referer::NoReferer;
|
*request.referer.borrow_mut() = Referer::NoReferer;
|
||||||
request.mode = RequestMode::CORSMode;
|
request.mode = RequestMode::CORSMode;
|
||||||
let fetch_response = fetch_sync(request);
|
let fetch_response = fetch_sync(request, None);
|
||||||
let _ = server.close();
|
let _ = server.close();
|
||||||
|
|
||||||
assert!(!fetch_response.is_network_error());
|
assert!(!fetch_response.is_network_error());
|
||||||
|
@ -390,9 +403,9 @@ fn test_fetch_response_is_opaque_filtered() {
|
||||||
|
|
||||||
// an origin mis-match will fall through to an Opaque filtered response
|
// an origin mis-match will fall through to an Opaque filtered response
|
||||||
let origin = Origin::Origin(UrlOrigin::new_opaque());
|
let origin = Origin::Origin(UrlOrigin::new_opaque());
|
||||||
let request = Request::new(url, Some(origin), false);
|
let request = Request::new(url, Some(origin), false, None);
|
||||||
*request.referer.borrow_mut() = Referer::NoReferer;
|
*request.referer.borrow_mut() = Referer::NoReferer;
|
||||||
let fetch_response = fetch_sync(request);
|
let fetch_response = fetch_sync(request, None);
|
||||||
let _ = server.close();
|
let _ = server.close();
|
||||||
|
|
||||||
assert!(!fetch_response.is_network_error());
|
assert!(!fetch_response.is_network_error());
|
||||||
|
@ -437,10 +450,10 @@ fn test_fetch_response_is_opaque_redirect_filtered() {
|
||||||
let (mut server, url) = make_server(handler);
|
let (mut server, url) = make_server(handler);
|
||||||
|
|
||||||
let origin = Origin::Origin(url.origin());
|
let origin = Origin::Origin(url.origin());
|
||||||
let request = Request::new(url, Some(origin), false);
|
let request = Request::new(url, Some(origin), false, None);
|
||||||
*request.referer.borrow_mut() = Referer::NoReferer;
|
*request.referer.borrow_mut() = Referer::NoReferer;
|
||||||
request.redirect_mode.set(RedirectMode::Manual);
|
request.redirect_mode.set(RedirectMode::Manual);
|
||||||
let fetch_response = fetch_sync(request);
|
let fetch_response = fetch_sync(request, None);
|
||||||
let _ = server.close();
|
let _ = server.close();
|
||||||
|
|
||||||
assert!(!fetch_response.is_network_error());
|
assert!(!fetch_response.is_network_error());
|
||||||
|
@ -471,13 +484,13 @@ fn test_fetch_with_local_urls_only() {
|
||||||
|
|
||||||
let do_fetch = |url: Url| {
|
let do_fetch = |url: Url| {
|
||||||
let origin = Origin::Origin(url.origin());
|
let origin = Origin::Origin(url.origin());
|
||||||
let mut request = Request::new(url, Some(origin), false);
|
let mut request = Request::new(url, Some(origin), false, None);
|
||||||
*request.referer.borrow_mut() = Referer::NoReferer;
|
*request.referer.borrow_mut() = Referer::NoReferer;
|
||||||
|
|
||||||
// Set the flag.
|
// Set the flag.
|
||||||
request.local_urls_only = true;
|
request.local_urls_only = true;
|
||||||
|
|
||||||
fetch_sync(request)
|
fetch_sync(request, None)
|
||||||
};
|
};
|
||||||
|
|
||||||
let local_url = Url::parse("about:blank").unwrap();
|
let local_url = Url::parse("about:blank").unwrap();
|
||||||
|
@ -512,9 +525,9 @@ fn setup_server_and_fetch(message: &'static [u8], redirect_cap: u32) -> Response
|
||||||
let (mut server, url) = make_server(handler);
|
let (mut server, url) = make_server(handler);
|
||||||
|
|
||||||
let origin = Origin::Origin(url.origin());
|
let origin = Origin::Origin(url.origin());
|
||||||
let request = Request::new(url, Some(origin), false);
|
let request = Request::new(url, Some(origin), false, None);
|
||||||
*request.referer.borrow_mut() = Referer::NoReferer;
|
*request.referer.borrow_mut() = Referer::NoReferer;
|
||||||
let fetch_response = fetch_sync(request);
|
let fetch_response = fetch_sync(request, None);
|
||||||
let _ = server.close();
|
let _ = server.close();
|
||||||
fetch_response
|
fetch_response
|
||||||
}
|
}
|
||||||
|
@ -595,11 +608,11 @@ fn test_fetch_redirect_updates_method_runner(tx: Sender<bool>, status_code: Stat
|
||||||
let (mut server, url) = make_server(handler);
|
let (mut server, url) = make_server(handler);
|
||||||
|
|
||||||
let origin = Origin::Origin(url.origin());
|
let origin = Origin::Origin(url.origin());
|
||||||
let request = Request::new(url, Some(origin), false);
|
let request = Request::new(url, Some(origin), false, None);
|
||||||
*request.referer.borrow_mut() = Referer::NoReferer;
|
*request.referer.borrow_mut() = Referer::NoReferer;
|
||||||
*request.method.borrow_mut() = method;
|
*request.method.borrow_mut() = method;
|
||||||
|
|
||||||
let _ = fetch_sync(request);
|
let _ = fetch_sync(request, None);
|
||||||
let _ = server.close();
|
let _ = server.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -670,7 +683,7 @@ fn test_fetch_async_returns_complete_response() {
|
||||||
let (mut server, url) = make_server(handler);
|
let (mut server, url) = make_server(handler);
|
||||||
|
|
||||||
let origin = Origin::Origin(url.origin());
|
let origin = Origin::Origin(url.origin());
|
||||||
let request = Request::new(url, Some(origin), false);
|
let request = Request::new(url, Some(origin), false, None);
|
||||||
*request.referer.borrow_mut() = Referer::NoReferer;
|
*request.referer.borrow_mut() = Referer::NoReferer;
|
||||||
|
|
||||||
let (tx, rx) = channel();
|
let (tx, rx) = channel();
|
||||||
|
@ -678,7 +691,7 @@ fn test_fetch_async_returns_complete_response() {
|
||||||
sender: tx.clone()
|
sender: tx.clone()
|
||||||
});
|
});
|
||||||
|
|
||||||
fetch_async(request, listener);
|
fetch_async(request, listener, None);
|
||||||
let fetch_response = rx.recv().unwrap();
|
let fetch_response = rx.recv().unwrap();
|
||||||
let _ = server.close();
|
let _ = server.close();
|
||||||
|
|
||||||
|
@ -695,7 +708,7 @@ fn test_opaque_filtered_fetch_async_returns_complete_response() {
|
||||||
|
|
||||||
// an origin mis-match will fall through to an Opaque filtered response
|
// an origin mis-match will fall through to an Opaque filtered response
|
||||||
let origin = Origin::Origin(UrlOrigin::new_opaque());
|
let origin = Origin::Origin(UrlOrigin::new_opaque());
|
||||||
let request = Request::new(url, Some(origin), false);
|
let request = Request::new(url, Some(origin), false, None);
|
||||||
*request.referer.borrow_mut() = Referer::NoReferer;
|
*request.referer.borrow_mut() = Referer::NoReferer;
|
||||||
|
|
||||||
let (tx, rx) = channel();
|
let (tx, rx) = channel();
|
||||||
|
@ -703,7 +716,7 @@ fn test_opaque_filtered_fetch_async_returns_complete_response() {
|
||||||
sender: tx.clone()
|
sender: tx.clone()
|
||||||
});
|
});
|
||||||
|
|
||||||
fetch_async(request, listener);
|
fetch_async(request, listener, None);
|
||||||
let fetch_response = rx.recv().unwrap();
|
let fetch_response = rx.recv().unwrap();
|
||||||
let _ = server.close();
|
let _ = server.close();
|
||||||
|
|
||||||
|
@ -735,7 +748,7 @@ fn test_opaque_redirect_filtered_fetch_async_returns_complete_response() {
|
||||||
let (mut server, url) = make_server(handler);
|
let (mut server, url) = make_server(handler);
|
||||||
|
|
||||||
let origin = Origin::Origin(url.origin());
|
let origin = Origin::Origin(url.origin());
|
||||||
let request = Request::new(url, Some(origin), false);
|
let request = Request::new(url, Some(origin), false, None);
|
||||||
*request.referer.borrow_mut() = Referer::NoReferer;
|
*request.referer.borrow_mut() = Referer::NoReferer;
|
||||||
request.redirect_mode.set(RedirectMode::Manual);
|
request.redirect_mode.set(RedirectMode::Manual);
|
||||||
|
|
||||||
|
@ -744,10 +757,83 @@ fn test_opaque_redirect_filtered_fetch_async_returns_complete_response() {
|
||||||
sender: tx.clone()
|
sender: tx.clone()
|
||||||
});
|
});
|
||||||
|
|
||||||
fetch_async(request, listener);
|
fetch_async(request, listener, None);
|
||||||
let fetch_response = rx.recv().unwrap();
|
let fetch_response = rx.recv().unwrap();
|
||||||
let _ = server.close();
|
let _ = server.close();
|
||||||
|
|
||||||
assert_eq!(fetch_response.response_type, ResponseType::OpaqueRedirect);
|
assert_eq!(fetch_response.response_type, ResponseType::OpaqueRedirect);
|
||||||
assert_eq!(response_is_done(&fetch_response), true);
|
assert_eq!(response_is_done(&fetch_response), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_fetch_with_devtools() {
|
||||||
|
static MESSAGE: &'static [u8] = b"Yay!";
|
||||||
|
let handler = move |_: HyperRequest, response: HyperResponse| {
|
||||||
|
response.send(MESSAGE).unwrap();
|
||||||
|
};
|
||||||
|
|
||||||
|
let (mut server, url) = make_server(handler);
|
||||||
|
|
||||||
|
let origin = Origin::Origin(url.origin());
|
||||||
|
let pipeline_id = PipelineId::fake_root_pipeline_id();
|
||||||
|
let request = Request::new(url.clone(), Some(origin), false, Some(pipeline_id));
|
||||||
|
*request.referer.borrow_mut() = Referer::NoReferer;
|
||||||
|
|
||||||
|
let (devtools_chan, devtools_port) = channel::<DevtoolsControlMsg>();
|
||||||
|
|
||||||
|
let _ = fetch_sync(request, Some(devtools_chan));
|
||||||
|
let _ = server.close();
|
||||||
|
|
||||||
|
// notification received from devtools
|
||||||
|
let devhttprequest = expect_devtools_http_request(&devtools_port);
|
||||||
|
let mut devhttpresponse = expect_devtools_http_response(&devtools_port);
|
||||||
|
|
||||||
|
//Creating default headers for request
|
||||||
|
let mut headers = Headers::new();
|
||||||
|
|
||||||
|
headers.set(AcceptEncoding(vec![
|
||||||
|
qitem(Encoding::Gzip),
|
||||||
|
qitem(Encoding::Deflate),
|
||||||
|
qitem(Encoding::EncodingExt("br".to_owned()))
|
||||||
|
]));
|
||||||
|
|
||||||
|
headers.set(Host { hostname: url.host_str().unwrap().to_owned() , port: url.port().to_owned() });
|
||||||
|
|
||||||
|
let accept = Accept(vec![qitem(Mime(TopLevel::Star, SubLevel::Star, vec![]))]);
|
||||||
|
headers.set(accept);
|
||||||
|
|
||||||
|
let mut en_us: LanguageTag = Default::default();
|
||||||
|
en_us.language = Some("en".to_owned());
|
||||||
|
en_us.region = Some("US".to_owned());
|
||||||
|
headers.set(AcceptLanguage(vec![qitem(en_us)]));
|
||||||
|
|
||||||
|
headers.set(UserAgent(DEFAULT_USER_AGENT.to_owned()));
|
||||||
|
|
||||||
|
let httprequest = DevtoolsHttpRequest {
|
||||||
|
url: url,
|
||||||
|
method: Method::Get,
|
||||||
|
headers: headers,
|
||||||
|
body: None,
|
||||||
|
pipeline_id: pipeline_id,
|
||||||
|
startedDateTime: devhttprequest.startedDateTime,
|
||||||
|
timeStamp: devhttprequest.timeStamp,
|
||||||
|
connect_time: devhttprequest.connect_time,
|
||||||
|
send_time: devhttprequest.send_time,
|
||||||
|
is_xhr: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
let content = "Yay!";
|
||||||
|
let mut response_headers = Headers::new();
|
||||||
|
response_headers.set(ContentLength(content.len() as u64));
|
||||||
|
devhttpresponse.headers.as_mut().unwrap().remove::<Date>();
|
||||||
|
|
||||||
|
let httpresponse = DevtoolsHttpResponse {
|
||||||
|
headers: Some(response_headers),
|
||||||
|
status: Some(RawStatus(200, Cow::Borrowed("OK"))),
|
||||||
|
body: None,
|
||||||
|
pipeline_id: pipeline_id,
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_eq!(devhttprequest, httprequest);
|
||||||
|
assert_eq!(devhttpresponse, httpresponse);
|
||||||
|
}
|
||||||
|
|
|
@ -339,7 +339,7 @@ impl HttpRequest for AssertMustHaveBodyRequest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expect_devtools_http_request(devtools_port: &Receiver<DevtoolsControlMsg>) -> DevtoolsHttpRequest {
|
pub fn expect_devtools_http_request(devtools_port: &Receiver<DevtoolsControlMsg>) -> DevtoolsHttpRequest {
|
||||||
match devtools_port.recv().unwrap() {
|
match devtools_port.recv().unwrap() {
|
||||||
DevtoolsControlMsg::FromChrome(
|
DevtoolsControlMsg::FromChrome(
|
||||||
ChromeToDevtoolsControlMsg::NetworkEvent(_, net_event)) => {
|
ChromeToDevtoolsControlMsg::NetworkEvent(_, net_event)) => {
|
||||||
|
@ -355,7 +355,7 @@ fn expect_devtools_http_request(devtools_port: &Receiver<DevtoolsControlMsg>) ->
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expect_devtools_http_response(devtools_port: &Receiver<DevtoolsControlMsg>) -> DevtoolsHttpResponse {
|
pub fn expect_devtools_http_response(devtools_port: &Receiver<DevtoolsControlMsg>) -> DevtoolsHttpResponse {
|
||||||
match devtools_port.recv().unwrap() {
|
match devtools_port.recv().unwrap() {
|
||||||
DevtoolsControlMsg::FromChrome(
|
DevtoolsControlMsg::FromChrome(
|
||||||
ChromeToDevtoolsControlMsg::NetworkEvent(_, net_event_response)) => {
|
ChromeToDevtoolsControlMsg::NetworkEvent(_, net_event_response)) => {
|
||||||
|
@ -526,6 +526,7 @@ fn test_request_and_response_data_with_network_messages() {
|
||||||
timeStamp: devhttprequest.timeStamp,
|
timeStamp: devhttprequest.timeStamp,
|
||||||
connect_time: devhttprequest.connect_time,
|
connect_time: devhttprequest.connect_time,
|
||||||
send_time: devhttprequest.send_time,
|
send_time: devhttprequest.send_time,
|
||||||
|
is_xhr: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let content = "Yay!";
|
let content = "Yay!";
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue