mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
Update fetch attributes to match the new spec
This commit is contained in:
parent
dbceb60455
commit
96971244ac
4 changed files with 231 additions and 161 deletions
|
@ -10,11 +10,12 @@
|
|||
//! with CORSRequest being expanded into FetchRequest (etc)
|
||||
|
||||
use hyper::method::Method;
|
||||
use net_traits::request::Origin;
|
||||
use std::ascii::AsciiExt;
|
||||
use std::sync::mpsc::{Sender, Receiver, channel};
|
||||
use time;
|
||||
use time::{now, Timespec};
|
||||
use url::{Origin, Url};
|
||||
use url::Url;
|
||||
|
||||
/// Union type for CORS cache entries
|
||||
///
|
||||
|
|
|
@ -16,7 +16,7 @@ use hyper::header::{QualityItem, q, qitem, Referer as RefererHeader, UserAgent};
|
|||
use hyper::method::Method;
|
||||
use hyper::mime::{Attr, Mime, SubLevel, TopLevel, Value};
|
||||
use hyper::status::StatusCode;
|
||||
use net_traits::request::{CacheMode, Context, ContextFrameType, CredentialsMode};
|
||||
use net_traits::request::{CacheMode, CredentialsMode, Type, Origin, Window};
|
||||
use net_traits::request::{RedirectMode, Referer, Request, RequestMode, ResponseTainting};
|
||||
use net_traits::response::{CacheState, HttpsState, TerminationReason};
|
||||
use net_traits::response::{Response, ResponseBody, ResponseType};
|
||||
|
@ -29,71 +29,82 @@ use std::rc::Rc;
|
|||
use std::str::FromStr;
|
||||
use std::thread;
|
||||
use url::idna::domain_to_ascii;
|
||||
use url::{Origin, OpaqueOrigin, Url, UrlParser, whatwg_scheme_type_mapper};
|
||||
use url::{Origin as UrlOrigin, OpaqueOrigin, Url, UrlParser, whatwg_scheme_type_mapper};
|
||||
use util::thread::spawn_named;
|
||||
|
||||
pub fn fetch_async(request: Request, cors_flag: bool, listener: Box<AsyncFetchListener + Send>) {
|
||||
spawn_named(format!("fetch for {:?}", request.get_last_url_string()), move || {
|
||||
pub fn fetch_async(request: Request, listener: Box<AsyncFetchListener + Send>) {
|
||||
spawn_named(format!("fetch for {:?}", request.current_url_string()), move || {
|
||||
let request = Rc::new(request);
|
||||
let res = fetch(request, cors_flag);
|
||||
let res = fetch(request);
|
||||
listener.response_available(res);
|
||||
})
|
||||
}
|
||||
|
||||
/// [Fetch](https://fetch.spec.whatwg.org#concept-fetch)
|
||||
pub fn fetch(request: Rc<Request>, cors_flag: bool) -> Response {
|
||||
pub fn fetch(request: Rc<Request>) -> Response {
|
||||
|
||||
// Step 1
|
||||
if request.context != Context::Fetch && !request.headers.borrow().has::<Accept>() {
|
||||
|
||||
// Substep 1
|
||||
let value = match request.context {
|
||||
|
||||
Context::Favicon | Context::Image | Context::ImageSet
|
||||
=> vec![qitem(Mime(TopLevel::Image, SubLevel::Png, vec![])),
|
||||
// FIXME: This should properly generate a MimeType that has a
|
||||
// SubLevel of svg+xml (https://github.com/hyperium/mime.rs/issues/22)
|
||||
qitem(Mime(TopLevel::Image, SubLevel::Ext("svg+xml".to_owned()), vec![])),
|
||||
QualityItem::new(Mime(TopLevel::Image, SubLevel::Star, vec![]), q(0.8)),
|
||||
QualityItem::new(Mime(TopLevel::Star, SubLevel::Star, vec![]), q(0.5))],
|
||||
|
||||
Context::Form | Context::Frame | Context::Hyperlink |
|
||||
Context::IFrame | Context::Location | Context::MetaRefresh |
|
||||
Context::PreRender
|
||||
=> vec![qitem(Mime(TopLevel::Text, SubLevel::Html, vec![])),
|
||||
// FIXME: This should properly generate a MimeType that has a
|
||||
// SubLevel of xhtml+xml (https://github.com/hyperium/mime.rs/issues/22)
|
||||
qitem(Mime(TopLevel::Application, SubLevel::Ext("xhtml+xml".to_owned()), vec![])),
|
||||
QualityItem::new(Mime(TopLevel::Application, SubLevel::Xml, vec![]), q(0.9)),
|
||||
QualityItem::new(Mime(TopLevel::Star, SubLevel::Star, vec![]), q(0.8))],
|
||||
|
||||
Context::Internal if request.context_frame_type != ContextFrameType::ContextNone
|
||||
=> vec![qitem(Mime(TopLevel::Text, SubLevel::Html, vec![])),
|
||||
// FIXME: This should properly generate a MimeType that has a
|
||||
// SubLevel of xhtml+xml (https://github.com/hyperium/mime.rs/issues/22)
|
||||
qitem(Mime(TopLevel::Application, SubLevel::Ext("xhtml+xml".to_owned()), vec![])),
|
||||
QualityItem::new(Mime(TopLevel::Application, SubLevel::Xml, vec![]), q(0.9)),
|
||||
QualityItem::new(Mime(TopLevel::Star, SubLevel::Star, vec![]), q(0.8))],
|
||||
|
||||
Context::Style
|
||||
=> vec![qitem(Mime(TopLevel::Text, SubLevel::Css, vec![])),
|
||||
QualityItem::new(Mime(TopLevel::Star, SubLevel::Star, vec![]), q(0.1))],
|
||||
_ => vec![qitem(Mime(TopLevel::Star, SubLevel::Star, vec![]))]
|
||||
};
|
||||
|
||||
// Substep 2
|
||||
request.headers.borrow_mut().set(Accept(value));
|
||||
if request.window.get() == Window::Client {
|
||||
// TODO: Set window to request's client object if client is a Window object
|
||||
} else {
|
||||
request.window.set(Window::NoWindow);
|
||||
}
|
||||
|
||||
// Step 2
|
||||
if request.context != Context::Fetch && !request.headers.borrow().has::<AcceptLanguage>() {
|
||||
if *request.origin.borrow() == Origin::Client {
|
||||
// TODO: set request's origin to request's client's origin
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
// Step 3
|
||||
if !request.headers.borrow().has::<Accept>() {
|
||||
|
||||
let value = match request.type_ {
|
||||
|
||||
// Substep 2
|
||||
_ if request.is_navigation_request() =>
|
||||
vec![qitem(Mime(TopLevel::Text, SubLevel::Html, vec![])),
|
||||
// FIXME: This should properly generate a MimeType that has a
|
||||
// SubLevel of xhtml+xml (https://github.com/hyperium/mime.rs/issues/22)
|
||||
qitem(Mime(TopLevel::Application, SubLevel::Ext("xhtml+xml".to_owned()), vec![])),
|
||||
QualityItem::new(Mime(TopLevel::Application, SubLevel::Xml, vec![]), q(0.9)),
|
||||
QualityItem::new(Mime(TopLevel::Star, SubLevel::Star, vec![]), q(0.8))],
|
||||
|
||||
// Substep 3
|
||||
Type::Image =>
|
||||
vec![qitem(Mime(TopLevel::Image, SubLevel::Png, vec![])),
|
||||
// FIXME: This should properly generate a MimeType that has a
|
||||
// SubLevel of svg+xml (https://github.com/hyperium/mime.rs/issues/22)
|
||||
qitem(Mime(TopLevel::Image, SubLevel::Ext("svg+xml".to_owned()), vec![])),
|
||||
QualityItem::new(Mime(TopLevel::Image, SubLevel::Star, vec![]), q(0.8)),
|
||||
QualityItem::new(Mime(TopLevel::Star, SubLevel::Star, vec![]), q(0.5))],
|
||||
|
||||
// Substep 3
|
||||
Type::Style =>
|
||||
vec![qitem(Mime(TopLevel::Text, SubLevel::Css, vec![])),
|
||||
QualityItem::new(Mime(TopLevel::Star, SubLevel::Star, vec![]), q(0.1))],
|
||||
// Substep 1
|
||||
_ => vec![qitem(Mime(TopLevel::Star, SubLevel::Star, vec![]))]
|
||||
};
|
||||
|
||||
// Substep 4
|
||||
request.headers.borrow_mut().set(Accept(value));
|
||||
}
|
||||
|
||||
// Step 4
|
||||
if !request.headers.borrow().has::<AcceptLanguage>() {
|
||||
request.headers.borrow_mut().set(AcceptLanguage(vec![qitem("en-US".parse().unwrap())]));
|
||||
}
|
||||
|
||||
// Step 5
|
||||
// TODO: Figure out what a Priority object is
|
||||
// Step 3
|
||||
// Step 4
|
||||
main_fetch(request, cors_flag, false)
|
||||
|
||||
// Step 6
|
||||
if request.is_subresource_request() {
|
||||
// TODO: create a fetch record and append it to request's client's fetch group list
|
||||
}
|
||||
// Step 7
|
||||
main_fetch(request, false, false)
|
||||
}
|
||||
|
||||
/// [Main fetch](https://fetch.spec.whatwg.org/#concept-main-fetch)
|
||||
|
@ -137,9 +148,13 @@ fn main_fetch(request: Rc<Request>, cors_flag: bool, recursive_flag: bool) -> Re
|
|||
let mut response = if response.is_none() {
|
||||
|
||||
let current_url = request.current_url();
|
||||
let origin_match = *request.origin.borrow() == current_url.origin();
|
||||
let same_origin = if let Origin::Origin(ref origin) = *request.origin.borrow() {
|
||||
*origin == current_url.origin()
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
if (!cors_flag && origin_match) ||
|
||||
if (!cors_flag && same_origin) ||
|
||||
(current_url.scheme == "data" && request.same_origin_data.get()) ||
|
||||
current_url.scheme == "about" ||
|
||||
request.mode == RequestMode::Navigate {
|
||||
|
@ -158,13 +173,13 @@ fn main_fetch(request: Rc<Request>, cors_flag: bool, recursive_flag: bool) -> Re
|
|||
|
||||
} else if request.use_cors_preflight ||
|
||||
(request.unsafe_request &&
|
||||
(!is_simple_method(&request.method.borrow()) ||
|
||||
request.headers.borrow().iter().any(|h| !is_simple_header(&h)))) {
|
||||
(!is_simple_method(&request.method.borrow()) ||
|
||||
request.headers.borrow().iter().any(|h| !is_simple_header(&h)))) {
|
||||
|
||||
request.response_tainting.set(ResponseTainting::CORSTainting);
|
||||
request.redirect_mode.set(RedirectMode::Error);
|
||||
let response = http_fetch(request.clone(), BasicCORSCache::new(), true, true, false);
|
||||
if Response::is_network_error(&response) {
|
||||
if response.is_network_error() {
|
||||
// TODO clear cache entries using request
|
||||
}
|
||||
response
|
||||
|
@ -197,7 +212,7 @@ fn main_fetch(request: Rc<Request>, cors_flag: bool, recursive_flag: bool) -> Re
|
|||
};
|
||||
|
||||
// Step 12
|
||||
let mut internal_response = if Response::is_network_error(&response) {
|
||||
let mut internal_response = if response.is_network_error() {
|
||||
Rc::new(Response::network_error())
|
||||
} else {
|
||||
response.internal_response.clone().unwrap()
|
||||
|
@ -207,7 +222,7 @@ fn main_fetch(request: Rc<Request>, cors_flag: bool, recursive_flag: bool) -> Re
|
|||
// TODO this step
|
||||
|
||||
// Step 14
|
||||
if !Response::is_network_error(&response) && (is_null_body_status(&internal_response.status) ||
|
||||
if !response.is_network_error() && (is_null_body_status(&internal_response.status) ||
|
||||
match *request.method.borrow() {
|
||||
Method::Head | Method::Connect => true,
|
||||
_ => false })
|
||||
|
@ -219,7 +234,7 @@ fn main_fetch(request: Rc<Request>, cors_flag: bool, recursive_flag: bool) -> Re
|
|||
|
||||
// Step 15
|
||||
// TODO be able to compare response integrity against request integrity metadata
|
||||
// if !Response::is_network_error(&response) {
|
||||
// if !response.is_network_error() {
|
||||
|
||||
// // Substep 1
|
||||
// // TODO wait for response
|
||||
|
@ -306,7 +321,7 @@ fn http_fetch_async(request: Request,
|
|||
authentication_fetch_flag: bool,
|
||||
listener: Box<AsyncFetchListener + Send>) {
|
||||
|
||||
spawn_named(format!("http_fetch for {:?}", request.get_last_url_string()), move || {
|
||||
spawn_named(format!("http_fetch for {:?}", request.current_url_string()), move || {
|
||||
let request = Rc::new(request);
|
||||
let res = http_fetch(request, BasicCORSCache::new(),
|
||||
cors_flag, cors_preflight_flag,
|
||||
|
@ -444,7 +459,7 @@ fn http_fetch(request: Rc<Request>,
|
|||
},
|
||||
RedirectMode::Follow => Rc::new(http_redirect_fetch(request, response, cors_flag))
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// Code 401
|
||||
StatusCode::Unauthorized => {
|
||||
|
@ -544,7 +559,11 @@ fn http_redirect_fetch(request: Rc<Request>,
|
|||
// Step 9
|
||||
request.same_origin_data.set(false);
|
||||
|
||||
let same_origin = *request.origin.borrow() == location_url.origin();
|
||||
let same_origin = if let Origin::Origin(ref origin) = *request.origin.borrow() {
|
||||
*origin == request.current_url().origin()
|
||||
} else {
|
||||
false
|
||||
};
|
||||
let has_credentials = has_credentials(&location_url);
|
||||
|
||||
// Step 10
|
||||
|
@ -559,7 +578,7 @@ fn http_redirect_fetch(request: Rc<Request>,
|
|||
|
||||
// Step 12
|
||||
if cors_flag && !same_origin {
|
||||
*request.origin.borrow_mut() = Origin::UID(OpaqueOrigin::new());
|
||||
*request.origin.borrow_mut() = Origin::Origin(UrlOrigin::UID(OpaqueOrigin::new()));
|
||||
}
|
||||
|
||||
// Step 13
|
||||
|
@ -626,7 +645,7 @@ fn http_network_or_cache_fetch(request: Rc<Request>,
|
|||
};
|
||||
|
||||
// Step 7
|
||||
if http_request.omit_origin_header == false {
|
||||
if http_request.omit_origin_header.get() == false {
|
||||
// TODO update this when https://github.com/hyperium/hyper/pull/691 is finished
|
||||
// http_request.headers.borrow_mut().set_raw("origin", origin);
|
||||
}
|
||||
|
@ -853,7 +872,7 @@ fn http_network_fetch(request: Rc<Request>,
|
|||
// TODO this step isn't possible yet
|
||||
|
||||
// Step 8
|
||||
if Response::is_network_error(&response) && request.cache_mode.get() == CacheMode::NoStore {
|
||||
if response.is_network_error() && request.cache_mode.get() == CacheMode::NoStore {
|
||||
// TODO update response in the HTTP cache for request
|
||||
}
|
||||
|
||||
|
@ -933,13 +952,14 @@ fn cors_check(request: Rc<Request>, response: &Response) -> Result<(), ()> {
|
|||
/// [ASCII serialisation of an origin](https://html.spec.whatwg.org/multipage/#ascii-serialisation-of-an-origin)
|
||||
fn ascii_serialise_origin(origin: &Origin) -> Result<String, ()> {
|
||||
|
||||
let result = match *origin {
|
||||
// Step 6
|
||||
match *origin {
|
||||
|
||||
// Step 1
|
||||
Origin::UID(_) => "null".to_owned(),
|
||||
Origin::Origin(UrlOrigin::UID(_)) => Ok("null".to_owned()),
|
||||
|
||||
// Step 2
|
||||
Origin::Tuple(ref scheme, ref host, ref port) => {
|
||||
Origin::Origin(UrlOrigin::Tuple(ref scheme, ref host, ref port)) => {
|
||||
|
||||
// Step 3
|
||||
// this step is handled by the format!()s later in the function
|
||||
|
@ -953,15 +973,13 @@ fn ascii_serialise_origin(origin: &Origin) -> Result<String, ()> {
|
|||
let default_port = whatwg_scheme_type_mapper(scheme).default_port();
|
||||
|
||||
if Some(*port) == default_port {
|
||||
format!("{}://{}", scheme, host)
|
||||
Ok(format!("{}://{}", scheme, host))
|
||||
} else {
|
||||
format!("{}://{}{}", scheme, host, port)
|
||||
Ok(format!("{}://{}{}", scheme, host, port))
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Step 6
|
||||
Ok(result)
|
||||
_ => Err(())
|
||||
}
|
||||
}
|
||||
|
||||
fn global_user_agent() -> String {
|
||||
|
|
|
@ -5,25 +5,38 @@
|
|||
use hyper::header::Headers;
|
||||
use hyper::method::Method;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use url::{Origin, Url};
|
||||
use url::{Origin as UrlOrigin, Url};
|
||||
|
||||
/// A [request context](https://fetch.spec.whatwg.org/#concept-request-context)
|
||||
/// An [initiator](https://fetch.spec.whatwg.org/#concept-request-initiator)
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
pub enum Context {
|
||||
Audio, Beacon, CSPreport, Download, Embed, Eventsource,
|
||||
Favicon, Fetch, Font, Form, Frame, Hyperlink, IFrame, Image,
|
||||
ImageSet, Import, Internal, Location, Manifest, MetaRefresh, Object,
|
||||
Ping, Plugin, Prefetch, PreRender, Script, ServiceWorker, SharedWorker,
|
||||
Subresource, Style, Track, Video, Worker, XMLHttpRequest, XSLT
|
||||
pub enum Initiator {
|
||||
None,
|
||||
Download,
|
||||
ImageSet,
|
||||
Manifest,
|
||||
XSLT
|
||||
}
|
||||
|
||||
/// A [request context frame type](https://fetch.spec.whatwg.org/#concept-request-context-frame-type)
|
||||
/// A request [type](https://fetch.spec.whatwg.org/#concept-request-type)
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
pub enum ContextFrameType {
|
||||
Auxiliary,
|
||||
TopLevel,
|
||||
Nested,
|
||||
ContextNone
|
||||
pub enum Type {
|
||||
None, Audio, Font, Image,
|
||||
Script, Style, Track, Video
|
||||
}
|
||||
|
||||
/// A request [destination](https://fetch.spec.whatwg.org/#concept-request-destination)
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
pub enum Destination {
|
||||
None, Document, Embed, Font, Image, Manifest,
|
||||
Media, Object, Report, Script, ServiceWorker,
|
||||
SharedWorker, Style, Worker, XSLT
|
||||
}
|
||||
|
||||
/// A request [origin](https://fetch.spec.whatwg.org/#concept-request-origin)
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub enum Origin {
|
||||
Client,
|
||||
Origin(UrlOrigin)
|
||||
}
|
||||
|
||||
/// A [referer](https://fetch.spec.whatwg.org/#concept-request-referrer)
|
||||
|
@ -78,7 +91,16 @@ pub enum ResponseTainting {
|
|||
Opaque
|
||||
}
|
||||
|
||||
/// [Window](https://fetch.spec.whatwg.org/#concept-request-window)
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
pub enum Window {
|
||||
NoWindow,
|
||||
Client,
|
||||
// TODO: Environmental settings object
|
||||
}
|
||||
|
||||
/// [CORS settings attribute](https://html.spec.whatwg.org/multipage/#attr-crossorigin-anonymous)
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
pub enum CORSSettings {
|
||||
Anonymous,
|
||||
UseCredentials
|
||||
|
@ -89,103 +111,111 @@ pub enum CORSSettings {
|
|||
pub struct Request {
|
||||
pub method: RefCell<Method>,
|
||||
pub local_urls_only: bool,
|
||||
// Use the last method on url_list to act as spec url field
|
||||
pub url_list: RefCell<Vec<Url>>,
|
||||
pub sanboxed_storage_area_urls: bool,
|
||||
pub headers: RefCell<Headers>,
|
||||
pub unsafe_request: bool,
|
||||
pub body: RefCell<Option<Vec<u8>>>,
|
||||
pub preserve_content_codings: bool,
|
||||
// TODO: client object
|
||||
pub is_service_worker_global_scope: bool,
|
||||
// pub client: GlobalRef, // XXXManishearth copy over only the relevant fields of the global scope,
|
||||
// not the entire scope to avoid the libscript dependency
|
||||
pub is_service_worker_global_scope: bool,
|
||||
pub window: Cell<Window>,
|
||||
// TODO: target browsing context
|
||||
pub keep_alive: Cell<bool>,
|
||||
pub skip_service_worker: Cell<bool>,
|
||||
pub context: Context,
|
||||
pub context_frame_type: ContextFrameType,
|
||||
pub initiator: Initiator,
|
||||
pub type_: Type,
|
||||
pub destination: Destination,
|
||||
// TODO: priority object
|
||||
pub origin: RefCell<Origin>,
|
||||
pub force_origin_header: bool,
|
||||
pub omit_origin_header: bool,
|
||||
pub omit_origin_header: Cell<bool>,
|
||||
pub same_origin_data: Cell<bool>,
|
||||
pub referer: Referer,
|
||||
pub authentication: bool,
|
||||
// TODO: referrer policy
|
||||
pub synchronous: bool,
|
||||
pub use_cors_preflight: bool,
|
||||
pub mode: RequestMode,
|
||||
pub use_cors_preflight: bool,
|
||||
pub credentials_mode: CredentialsMode,
|
||||
pub use_url_credentials: bool,
|
||||
pub cache_mode: Cell<CacheMode>,
|
||||
pub redirect_mode: Cell<RedirectMode>,
|
||||
pub integrity_metadata: RefCell<String>,
|
||||
// Use the last method on url_list to act as spec current url field, and
|
||||
// first method to act as spec url field
|
||||
pub url_list: RefCell<Vec<Url>>,
|
||||
pub redirect_count: Cell<u32>,
|
||||
pub response_tainting: Cell<ResponseTainting>
|
||||
pub response_tainting: Cell<ResponseTainting>,
|
||||
pub done: Cell<bool>
|
||||
}
|
||||
|
||||
impl Request {
|
||||
pub fn new(url: Url,
|
||||
context: Context,
|
||||
origin: Origin,
|
||||
origin: Option<Origin>,
|
||||
is_service_worker_global_scope: bool) -> Request {
|
||||
Request {
|
||||
method: RefCell::new(Method::Get),
|
||||
local_urls_only: false,
|
||||
url_list: RefCell::new(vec![url]),
|
||||
sanboxed_storage_area_urls: false,
|
||||
headers: RefCell::new(Headers::new()),
|
||||
unsafe_request: false,
|
||||
body: RefCell::new(None),
|
||||
preserve_content_codings: false,
|
||||
is_service_worker_global_scope: is_service_worker_global_scope,
|
||||
window: Cell::new(Window::Client),
|
||||
keep_alive: Cell::new(false),
|
||||
skip_service_worker: Cell::new(false),
|
||||
context: context,
|
||||
context_frame_type: ContextFrameType::ContextNone,
|
||||
origin: RefCell::new(origin),
|
||||
force_origin_header: false,
|
||||
omit_origin_header: false,
|
||||
initiator: Initiator::None,
|
||||
type_: Type::None,
|
||||
destination: Destination::None,
|
||||
origin: RefCell::new(origin.unwrap_or(Origin::Client)),
|
||||
omit_origin_header: Cell::new(false),
|
||||
same_origin_data: Cell::new(false),
|
||||
referer: Referer::Client,
|
||||
authentication: false,
|
||||
synchronous: false,
|
||||
use_cors_preflight: false,
|
||||
mode: RequestMode::NoCORS,
|
||||
use_cors_preflight: false,
|
||||
credentials_mode: CredentialsMode::Omit,
|
||||
use_url_credentials: false,
|
||||
cache_mode: Cell::new(CacheMode::Default),
|
||||
redirect_mode: Cell::new(RedirectMode::Follow),
|
||||
integrity_metadata: RefCell::new(String::new()),
|
||||
url_list: RefCell::new(vec![url]),
|
||||
redirect_count: Cell::new(0),
|
||||
response_tainting: Cell::new(ResponseTainting::Basic)
|
||||
response_tainting: Cell::new(ResponseTainting::Basic),
|
||||
done: Cell::new(false)
|
||||
}
|
||||
}
|
||||
|
||||
/// https://html.spec.whatwg.org/multipage/#create-a-potential-cors-request
|
||||
pub fn potential_cors_request(url: Url,
|
||||
cors_attribute_state: Option<CORSSettings>,
|
||||
context: Context,
|
||||
is_service_worker_global_scope: bool,
|
||||
same_origin_fallback: bool) -> Request {
|
||||
let origin = url.origin();
|
||||
cors_attribute_state: Option<CORSSettings>,
|
||||
is_service_worker_global_scope: bool,
|
||||
same_origin_fallback: bool) -> Request {
|
||||
Request {
|
||||
method: RefCell::new(Method::Get),
|
||||
local_urls_only: false,
|
||||
url_list: RefCell::new(vec![url]),
|
||||
sanboxed_storage_area_urls: false,
|
||||
headers: RefCell::new(Headers::new()),
|
||||
unsafe_request: false,
|
||||
body: RefCell::new(None),
|
||||
preserve_content_codings: false,
|
||||
is_service_worker_global_scope: is_service_worker_global_scope,
|
||||
window: Cell::new(Window::Client),
|
||||
keep_alive: Cell::new(false),
|
||||
skip_service_worker: Cell::new(false),
|
||||
context: context,
|
||||
context_frame_type: ContextFrameType::ContextNone,
|
||||
origin: RefCell::new(origin),
|
||||
force_origin_header: false,
|
||||
initiator: Initiator::None,
|
||||
type_: Type::None,
|
||||
destination: Destination::None,
|
||||
origin: RefCell::new(Origin::Client),
|
||||
omit_origin_header: Cell::new(false),
|
||||
same_origin_data: Cell::new(false),
|
||||
omit_origin_header: false,
|
||||
referer: Referer::Client,
|
||||
authentication: false,
|
||||
synchronous: false,
|
||||
use_cors_preflight: false,
|
||||
// Step 1-2
|
||||
mode: match cors_attribute_state {
|
||||
Some(_) => RequestMode::CORSMode,
|
||||
None if same_origin_fallback => RequestMode::SameOrigin,
|
||||
None => RequestMode::NoCORS
|
||||
},
|
||||
use_cors_preflight: false,
|
||||
// Step 3-4
|
||||
credentials_mode: match cors_attribute_state {
|
||||
Some(CORSSettings::Anonymous) => CredentialsMode::CredentialsSameOrigin,
|
||||
|
@ -194,16 +224,37 @@ impl Request {
|
|||
use_url_credentials: true,
|
||||
cache_mode: Cell::new(CacheMode::Default),
|
||||
redirect_mode: Cell::new(RedirectMode::Follow),
|
||||
integrity_metadata: RefCell::new(String::new()),
|
||||
url_list: RefCell::new(vec![url]),
|
||||
redirect_count: Cell::new(0),
|
||||
response_tainting: Cell::new(ResponseTainting::Basic)
|
||||
response_tainting: Cell::new(ResponseTainting::Basic),
|
||||
done: Cell::new(false)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_last_url_string(&self) -> String {
|
||||
self.url_list.borrow().last().unwrap().serialize()
|
||||
pub fn url(&self) -> Url {
|
||||
self.url_list.borrow().first().unwrap().clone()
|
||||
}
|
||||
|
||||
pub fn current_url(&self) -> Url {
|
||||
self.url_list.borrow().last().unwrap().clone()
|
||||
}
|
||||
|
||||
pub fn current_url_string(&self) -> String {
|
||||
self.url_list.borrow().last().unwrap().serialize()
|
||||
}
|
||||
|
||||
pub fn is_navigation_request(&self) -> bool {
|
||||
self.destination == Destination::Document
|
||||
}
|
||||
|
||||
pub fn is_subresource_request(&self) -> bool {
|
||||
match self.destination {
|
||||
Destination::Font | Destination::Image | Destination::Manifest
|
||||
| Destination::Media | Destination::Script
|
||||
| Destination::Style | Destination::XSLT
|
||||
| Destination::None => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,14 +11,14 @@ use hyper::server::{Request as HyperRequest, Response as HyperResponse};
|
|||
use hyper::status::StatusCode;
|
||||
use hyper::uri::RequestUri;
|
||||
use net::fetch::methods::fetch;
|
||||
use net_traits::request::{Context, RedirectMode, Referer, Request, RequestMode};
|
||||
use net_traits::request::{Origin, RedirectMode, Referer, Request, RequestMode};
|
||||
use net_traits::response::{CacheState, Response, ResponseBody, ResponseType};
|
||||
use std::cell::Cell;
|
||||
use std::rc::Rc;
|
||||
use std::sync::{Arc, Mutex, mpsc};
|
||||
use time::{self, Duration};
|
||||
use unicase::UniCase;
|
||||
use url::{Origin, OpaqueOrigin, Url};
|
||||
use url::{Origin as UrlOrigin, OpaqueOrigin, Url};
|
||||
|
||||
// TODO write a struct that impls Handler for storing test values
|
||||
|
||||
|
@ -42,15 +42,15 @@ fn test_fetch_response_is_not_network_error() {
|
|||
};
|
||||
let (mut server, url) = make_server(handler);
|
||||
|
||||
let origin = url.origin();
|
||||
let mut request = Request::new(url, Context::Fetch, origin, false);
|
||||
let origin = Origin::Origin(url.origin());
|
||||
let mut request = Request::new(url, Some(origin), false);
|
||||
request.referer = Referer::NoReferer;
|
||||
let wrapped_request = Rc::new(request);
|
||||
|
||||
let fetch_response = fetch(wrapped_request, false);
|
||||
let fetch_response = fetch(wrapped_request);
|
||||
let _ = server.close();
|
||||
|
||||
if Response::is_network_error(&fetch_response) {
|
||||
if fetch_response.is_network_error() {
|
||||
panic!("fetch response shouldn't be a network error");
|
||||
}
|
||||
}
|
||||
|
@ -64,15 +64,15 @@ fn test_fetch_response_body_matches_const_message() {
|
|||
};
|
||||
let (mut server, url) = make_server(handler);
|
||||
|
||||
let origin = url.origin();
|
||||
let mut request = Request::new(url, Context::Fetch, origin, false);
|
||||
let origin = Origin::Origin(url.origin());
|
||||
let mut request = Request::new(url, Some(origin), false);
|
||||
request.referer = Referer::NoReferer;
|
||||
let wrapped_request = Rc::new(request);
|
||||
|
||||
let fetch_response = fetch(wrapped_request, false);
|
||||
let fetch_response = fetch(wrapped_request);
|
||||
let _ = server.close();
|
||||
|
||||
assert!(!Response::is_network_error(&fetch_response));
|
||||
assert!(!fetch_response.is_network_error());
|
||||
assert_eq!(fetch_response.response_type, ResponseType::Basic);
|
||||
|
||||
match *fetch_response.body.borrow() {
|
||||
|
@ -97,15 +97,15 @@ fn test_fetch_response_is_basic_filtered() {
|
|||
};
|
||||
let (mut server, url) = make_server(handler);
|
||||
|
||||
let origin = url.origin();
|
||||
let mut request = Request::new(url, Context::Fetch, origin, false);
|
||||
let origin = Origin::Origin(url.origin());
|
||||
let mut request = Request::new(url, Some(origin), false);
|
||||
request.referer = Referer::NoReferer;
|
||||
let wrapped_request = Rc::new(request);
|
||||
|
||||
let fetch_response = fetch(wrapped_request, false);
|
||||
let fetch_response = fetch(wrapped_request);
|
||||
let _ = server.close();
|
||||
|
||||
assert!(!Response::is_network_error(&fetch_response));
|
||||
assert!(!fetch_response.is_network_error());
|
||||
assert_eq!(fetch_response.response_type, ResponseType::Basic);
|
||||
|
||||
let headers = fetch_response.headers;
|
||||
|
@ -146,16 +146,16 @@ fn test_fetch_response_is_cors_filtered() {
|
|||
let (mut server, url) = make_server(handler);
|
||||
|
||||
// an origin mis-match will stop it from defaulting to a basic filtered response
|
||||
let origin = Origin::UID(OpaqueOrigin::new());
|
||||
let mut request = Request::new(url, Context::Fetch, origin, false);
|
||||
let origin = Origin::Origin(UrlOrigin::UID(OpaqueOrigin::new()));
|
||||
let mut request = Request::new(url, Some(origin), false);
|
||||
request.referer = Referer::NoReferer;
|
||||
request.mode = RequestMode::CORSMode;
|
||||
let wrapped_request = Rc::new(request);
|
||||
|
||||
let fetch_response = fetch(wrapped_request, false);
|
||||
let fetch_response = fetch(wrapped_request);
|
||||
let _ = server.close();
|
||||
|
||||
assert!(!Response::is_network_error(&fetch_response));
|
||||
assert!(!fetch_response.is_network_error());
|
||||
assert_eq!(fetch_response.response_type, ResponseType::CORS);
|
||||
|
||||
let headers = fetch_response.headers;
|
||||
|
@ -181,15 +181,15 @@ fn test_fetch_response_is_opaque_filtered() {
|
|||
let (mut server, url) = make_server(handler);
|
||||
|
||||
// an origin mis-match will fall through to an Opaque filtered response
|
||||
let origin = Origin::UID(OpaqueOrigin::new());
|
||||
let mut request = Request::new(url, Context::Fetch, origin, false);
|
||||
let origin = Origin::Origin(UrlOrigin::UID(OpaqueOrigin::new()));
|
||||
let mut request = Request::new(url, Some(origin), false);
|
||||
request.referer = Referer::NoReferer;
|
||||
let wrapped_request = Rc::new(request);
|
||||
|
||||
let fetch_response = fetch(wrapped_request, false);
|
||||
let fetch_response = fetch(wrapped_request);
|
||||
let _ = server.close();
|
||||
|
||||
assert!(!Response::is_network_error(&fetch_response));
|
||||
assert!(!fetch_response.is_network_error());
|
||||
assert_eq!(fetch_response.response_type, ResponseType::Opaque);
|
||||
|
||||
assert!(fetch_response.url_list.into_inner().len() == 0);
|
||||
|
@ -232,16 +232,16 @@ fn test_fetch_response_is_opaque_redirect_filtered() {
|
|||
|
||||
let (mut server, url) = make_server(handler);
|
||||
|
||||
let origin = url.origin();
|
||||
let mut request = Request::new(url, Context::Fetch, origin, false);
|
||||
let origin = Origin::Origin(url.origin());
|
||||
let mut request = Request::new(url, Some(origin), false);
|
||||
request.referer = Referer::NoReferer;
|
||||
request.redirect_mode = Cell::new(RedirectMode::Manual);
|
||||
let wrapped_request = Rc::new(request);
|
||||
|
||||
let fetch_response = fetch(wrapped_request, false);
|
||||
let fetch_response = fetch(wrapped_request);
|
||||
let _ = server.close();
|
||||
|
||||
assert!(!Response::is_network_error(&fetch_response));
|
||||
assert!(!fetch_response.is_network_error());
|
||||
assert_eq!(fetch_response.response_type, ResponseType::OpaqueRedirect);
|
||||
|
||||
// this also asserts that status message is "the empty byte sequence"
|
||||
|
@ -280,12 +280,12 @@ fn test_fetch_redirect_count(message: &'static [u8], redirect_cap: u32) -> Respo
|
|||
|
||||
let (mut server, url) = make_server(handler);
|
||||
|
||||
let origin = url.origin();
|
||||
let mut request = Request::new(url, Context::Fetch, origin, false);
|
||||
let origin = Origin::Origin(url.origin());
|
||||
let mut request = Request::new(url, Some(origin), false);
|
||||
request.referer = Referer::NoReferer;
|
||||
let wrapped_request = Rc::new(request);
|
||||
|
||||
let fetch_response = fetch(wrapped_request, false);
|
||||
let fetch_response = fetch(wrapped_request);
|
||||
let _ = server.close();
|
||||
fetch_response
|
||||
}
|
||||
|
@ -299,7 +299,7 @@ fn test_fetch_redirect_count_ceiling() {
|
|||
|
||||
let fetch_response = test_fetch_redirect_count(MESSAGE, redirect_cap);
|
||||
|
||||
assert!(!Response::is_network_error(&fetch_response));
|
||||
assert!(!fetch_response.is_network_error());
|
||||
assert_eq!(fetch_response.response_type, ResponseType::Basic);
|
||||
|
||||
match *fetch_response.body.borrow() {
|
||||
|
@ -319,7 +319,7 @@ fn test_fetch_redirect_count_failure() {
|
|||
|
||||
let fetch_response = test_fetch_redirect_count(MESSAGE, redirect_cap);
|
||||
|
||||
assert!(Response::is_network_error(&fetch_response));
|
||||
assert!(fetch_response.is_network_error());
|
||||
|
||||
match *fetch_response.body.borrow() {
|
||||
ResponseBody::Done(_) | ResponseBody::Receiving(_) => panic!(),
|
||||
|
@ -370,14 +370,14 @@ fn test_fetch_redirect_updates_method_runner(tx: mpsc::Sender<bool>, status_code
|
|||
};
|
||||
|
||||
let (mut server, url) = make_server(handler);
|
||||
let origin = url.origin();
|
||||
|
||||
let mut request = Request::new(url, Context::Fetch, origin, false);
|
||||
let origin = Origin::Origin(url.origin());
|
||||
let mut request = Request::new(url, Some(origin), false);
|
||||
request.referer = Referer::NoReferer;
|
||||
*request.method.borrow_mut() = method;
|
||||
let wrapped_request = Rc::new(request);
|
||||
|
||||
let _ = fetch(wrapped_request, false);
|
||||
let _ = fetch(wrapped_request);
|
||||
let _ = server.close();
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue