aboutsummaryrefslogtreecommitdiffstats
path: root/components/net/fetch
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2016-02-10 03:11:22 +0530
committerbors-servo <lbergstrom+bors@mozilla.com>2016-02-10 03:11:22 +0530
commitf1018b84a838ec8505f6a0bcb6e13286ce80a95c (patch)
tree1d899be179ddceffa4f56dfeabaaea1a4128de94 /components/net/fetch
parentcb8be1434f61e6bfe4639d42b1422329b0451a47 (diff)
parente8665d47ea5381bc6f07d7ff7d7b94bca23be767 (diff)
downloadservo-f1018b84a838ec8505f6a0bcb6e13286ce80a95c.tar.gz
servo-f1018b84a838ec8505f6a0bcb6e13286ce80a95c.zip
Auto merge of #9525 - nikkisquared:test_filtered_responses, r=asajeffrey
Test filtered responses and implement Cors Check Fetch step I've been writing tests for creating filtered responses. So far I have three of the four types being made (namely, Basic, CORS, and Opaque), and just need to figure out how to make an OpaqueRedirect filtered response, since it's handled separately from the others. I will also add more tests to ensure the content of the filtered responses matches the limitations placed by the specification. Along the way I implemented Cors Check, since it's required for the CORS filtered response. @jdm suggested I handle it in here, since it's such a small step, compared to other parts of Fetch. Since all the tests currently pass, and I've spent a while adding the Cors Check and other pieces, I figured now would be a good time to start having it reviewed. <!-- Reviewable:start --> [<img src="https://reviewable.io/review_button.svg" height="40" alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/9525) <!-- Reviewable:end -->
Diffstat (limited to 'components/net/fetch')
-rw-r--r--components/net/fetch/methods.rs92
-rw-r--r--components/net/fetch/response.rs6
2 files changed, 90 insertions, 8 deletions
diff --git a/components/net/fetch/methods.rs b/components/net/fetch/methods.rs
index 5aee648dc96..7cd93076185 100644
--- a/components/net/fetch/methods.rs
+++ b/components/net/fetch/methods.rs
@@ -9,6 +9,7 @@ use http_loader::{create_http_connector, obtain_response};
use hyper::client::response::Response as HyperResponse;
use hyper::header::{Accept, IfMatch, IfRange, IfUnmodifiedSince, Location};
use hyper::header::{AcceptLanguage, ContentLength, ContentLanguage, HeaderView};
+use hyper::header::{AccessControlAllowCredentials, AccessControlAllowOrigin};
use hyper::header::{Authorization, Basic, ContentEncoding, Encoding};
use hyper::header::{ContentType, Header, Headers, IfModifiedSince, IfNoneMatch};
use hyper::header::{QualityItem, q, qitem, Referer as RefererHeader, UserAgent};
@@ -27,7 +28,8 @@ use std::io::Read;
use std::rc::Rc;
use std::str::FromStr;
use std::thread;
-use url::{Origin, Url, UrlParser};
+use url::idna::domain_to_ascii;
+use url::{Origin, Url, UrlParser, whatwg_scheme_type_mapper};
use util::thread::spawn_named;
pub fn fetch_async(request: Request, cors_flag: bool, listener: Box<AsyncFetchListener + Send>) {
@@ -729,12 +731,12 @@ fn http_network_or_cache_fetch(request: Rc<Request>,
// Substep 1
// TODO this substep
- let cached_response: Option<Response> = None;
+ // let cached_response: Option<Response> = None;
// Substep 2
- if cached_response.is_none() {
- return Response::network_error();
- }
+ // if cached_response.is_none() {
+ // return Response::network_error();
+ // }
// Substep 3
@@ -860,10 +862,88 @@ fn preflight_fetch(request: Rc<Request>) -> Response {
/// [CORS check](https://fetch.spec.whatwg.org#concept-cors-check)
fn cors_check(request: Rc<Request>, response: &Response) -> Result<(), ()> {
- // TODO: Implement CORS check spec
+
+ // Step 1
+ // let headers = request.headers.borrow();
+ let origin = response.headers.get::<AccessControlAllowOrigin>().cloned();
+
+ // Step 2
+ let origin = try!(origin.ok_or(()));
+
+ // Step 3
+ if request.credentials_mode != CredentialsMode::Include &&
+ origin == AccessControlAllowOrigin::Any {
+ return Ok(());
+ }
+
+ // Step 4
+ let origin = match origin {
+ AccessControlAllowOrigin::Value(origin) => origin,
+ // if it's Any or Null at this point, I see nothing to do but return Err(())
+ _ => return Err(())
+ };
+
+ // strings are already utf-8 encoded, so I don't need to re-encode origin for this step
+ match ascii_serialise_origin(&request.origin) {
+ Ok(request_origin) => {
+ if request_origin != origin {
+ return Err(());
+ }
+ },
+ _ => return Err(())
+ }
+
+ // Step 5
+ if request.credentials_mode != CredentialsMode::Include {
+ return Ok(());
+ }
+
+ // Step 6
+ let credentials = request.headers.borrow().get::<AccessControlAllowCredentials>().cloned();
+
+ // Step 7
+ if credentials.is_some() {
+ return Ok(());
+ }
+
+ // Step 8
Err(())
}
+/// [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 1
+ Origin::UID(_) => "null".to_owned(),
+
+ // Step 2
+ Origin::Tuple(ref scheme, ref host, ref port) => {
+
+ // Step 3
+ // this step is handled by the format!()s later in the function
+
+ // Step 4
+ // TODO throw a SecurityError in a meaningful way
+ // let host = host.as_str();
+ let host = try!(domain_to_ascii(host.serialize().as_str()).or(Err(())));
+
+ // Step 5
+ let default_port = whatwg_scheme_type_mapper(scheme).default_port();
+
+ if Some(*port) == default_port {
+ format!("{}://{}", scheme, host)
+ } else {
+ format!("{}://{}{}", scheme, host, port)
+ }
+ }
+ };
+
+ // Step 6
+ Ok(result)
+}
+
fn global_user_agent() -> String {
// TODO have a better useragent string
const USER_AGENT_STRING: &'static str = "Servo";
diff --git a/components/net/fetch/response.rs b/components/net/fetch/response.rs
index 63b28de350d..ddb65a8e5e1 100644
--- a/components/net/fetch/response.rs
+++ b/components/net/fetch/response.rs
@@ -69,8 +69,8 @@ impl ResponseMethods for Response {
let headers = old_headers.iter().filter(|header| {
match &*header.name().to_ascii_lowercase() {
- "cache-control" | "content-language" |
- "content-type" | "expires" | "last-modified" | "Pragma" => true,
+ "cache-control" | "content-language" | "content-type" |
+ "expires" | "last-modified" | "pragma" => true,
"set-cookie" | "set-cookie2" => false,
header => {
let result =
@@ -88,12 +88,14 @@ impl ResponseMethods for Response {
response.headers = Headers::new();
response.status = None;
response.body = RefCell::new(ResponseBody::Empty);
+ response.cache_state = CacheState::None;
},
ResponseType::OpaqueRedirect => {
response.headers = Headers::new();
response.status = None;
response.body = RefCell::new(ResponseBody::Empty);
+ response.cache_state = CacheState::None;
}
}