Skip to content

Commit

Permalink
Auto merge of #15903 - servo:set-origin-header, r=Wafflespeanut
Browse files Browse the repository at this point in the history
Set Origin header in http_network_or_cache_fetch

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/15903)
<!-- Reviewable:end -->
  • Loading branch information
bors-servo committed Mar 10, 2017
2 parents 72128de + 186dec1 commit a11a3fe
Show file tree
Hide file tree
Showing 16 changed files with 93 additions and 250 deletions.
24 changes: 20 additions & 4 deletions components/net/http_loader.rs
Expand Up @@ -22,6 +22,7 @@ use hyper::header::{Authorization, Basic, CacheControl, CacheDirective, ContentE
use hyper::header::{ContentLength, Encoding, Header, Headers, Host, IfMatch, IfRange};
use hyper::header::{IfUnmodifiedSince, IfModifiedSince, IfNoneMatch, Location, Pragma, Quality};
use hyper::header::{QualityItem, Referer, SetCookie, UserAgent, qitem};
use hyper::header::Origin as HyperOrigin;
use hyper::method::Method;
use hyper::net::Fresh;
use hyper::status::StatusCode;
Expand Down Expand Up @@ -785,6 +786,15 @@ fn http_redirect_fetch(request: Rc<Request>,
main_fetch(request, cache, cors_flag, true, target, done_chan, context)
}

fn try_immutable_origin_to_hyper_origin(url_origin: &ImmutableOrigin) -> Option<HyperOrigin> {
match *url_origin {
// TODO (servo/servo#15569) Set "Origin: null" when hyper supports it
ImmutableOrigin::Opaque(_) => None,
ImmutableOrigin::Tuple(ref scheme, ref host, ref port) =>
Some(HyperOrigin::new(scheme.clone(), host.to_string(), Some(port.clone())))
}
}

/// [HTTP network or cache fetch](https://fetch.spec.whatwg.org#http-network-or-cache-fetch)
fn http_network_or_cache_fetch(request: Rc<Request>,
authentication_fetch_flag: bool,
Expand Down Expand Up @@ -843,10 +853,16 @@ fn http_network_or_cache_fetch(request: Rc<Request>,
};

// Step 9
if cors_flag ||
(*http_request.method.borrow() != Method::Get && *http_request.method.borrow() != Method::Head) {
// TODO update this when https://github.com/hyperium/hyper/pull/691 is finished
// http_request.headers.borrow_mut().set_raw("origin", origin);
if !http_request.omit_origin_header.get() {
let method = http_request.method.borrow();
if cors_flag || (*method != Method::Get && *method != Method::Head) {
debug_assert!(*http_request.origin.borrow() != Origin::Client);
if let Origin::Origin(ref url_origin) = *http_request.origin.borrow() {
if let Some(hyper_origin) = try_immutable_origin_to_hyper_origin(url_origin) {
http_request.headers.borrow_mut().set(hyper_origin)
}
}
}
}

// Step 10
Expand Down
74 changes: 69 additions & 5 deletions tests/unit/net/http_loader.rs
Expand Up @@ -12,8 +12,8 @@ use flate2::Compression;
use flate2::write::{DeflateEncoder, GzEncoder};
use hyper::LanguageTag;
use hyper::header::{Accept, AcceptEncoding, ContentEncoding, ContentLength, Cookie as CookieHeader};
use hyper::header::{AcceptLanguage, Authorization, Basic, Date};
use hyper::header::{Encoding, Headers, Host, Location, Quality, QualityItem, SetCookie, qitem};
use hyper::header::{AcceptLanguage, AccessControlAllowOrigin, Authorization, Basic, Date};
use hyper::header::{Encoding, Headers, Host, Location, Origin, Quality, QualityItem, SetCookie, qitem};
use hyper::header::{StrictTransportSecurity, UserAgent};
use hyper::method::Method;
use hyper::mime::{Mime, SubLevel, TopLevel};
Expand All @@ -27,12 +27,13 @@ use net::cookie_storage::CookieStorage;
use net::resource_thread::AuthCacheEntry;
use net_traits::{CookieSource, NetworkError};
use net_traits::hosts::replace_host_table;
use net_traits::request::{Request, RequestInit, CredentialsMode, Destination};
use net_traits::request::{Request, RequestInit, RequestMode, CredentialsMode, Destination};
use net_traits::response::ResponseBody;
use new_fetch_context;
use servo_url::ServoUrl;
use std::collections::HashMap;
use std::io::{Read, Write};
use std::str::FromStr;
use std::sync::{Arc, Mutex, RwLock, mpsc};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::mpsc::Receiver;
Expand Down Expand Up @@ -145,8 +146,13 @@ fn test_check_default_headers_loaded_in_every_request() {
assert!(response.status.unwrap().is_success());

// Testing for method.POST
headers.set(ContentLength(0 as u64));
*expected_headers.lock().unwrap() = Some(headers.clone());
let mut post_headers = headers.clone();
post_headers.set(ContentLength(0 as u64));
let url_str = url.as_str();
// request gets header "Origin: http://example.com" but expected_headers has
// "Origin: http://example.com/" which do not match for equality so strip trailing '/'
post_headers.set(Origin::from_str(&url_str[..url_str.len()-1]).unwrap());
*expected_headers.lock().unwrap() = Some(post_headers);
let request = Request::from_init(RequestInit {
url: url.clone(),
method: Method::Post,
Expand Down Expand Up @@ -1117,3 +1123,61 @@ fn test_auth_ui_needs_www_auth() {

assert_eq!(response.status.unwrap(), StatusCode::Unauthorized);
}

#[test]
fn test_origin_set() {
let origin_header = Arc::new(Mutex::new(None));
let origin_header_clone = origin_header.clone();
let handler = move |request: HyperRequest, mut resp: HyperResponse| {
let origin_header_clone = origin_header.clone();
resp.headers_mut().set(AccessControlAllowOrigin::Any);
match request.headers.get::<Origin>() {
None => assert_eq!(origin_header_clone.lock().unwrap().take(), None),
Some(h) => assert_eq!(*h, origin_header_clone.lock().unwrap().take().unwrap()),
}
};
let (mut server, url) = make_server(handler);

let mut origin = Origin::new(url.scheme(), url.host_str().unwrap(), url.port());
*origin_header_clone.lock().unwrap() = Some(origin.clone());
let request = Request::from_init(RequestInit {
url: url.clone(),
method: Method::Post,
body: None,
origin: url.clone(),
.. RequestInit::default()
});
let response = fetch(request, None);
assert!(response.status.unwrap().is_success());

let origin_url = ServoUrl::parse("http://example.com").unwrap();
origin = Origin::new(origin_url.scheme(), origin_url.host_str().unwrap(), origin_url.port());
// Test Origin header is set on Get request with CORS mode
let request = Request::from_init(RequestInit {
url: url.clone(),
method: Method::Get,
mode: RequestMode::CorsMode,
body: None,
origin: origin_url.clone(),
.. RequestInit::default()
});

*origin_header_clone.lock().unwrap() = Some(origin.clone());
let response = fetch(request, None);
assert!(response.status.unwrap().is_success());

// Test Origin header is not set on method Head
let request = Request::from_init(RequestInit {
url: url.clone(),
method: Method::Head,
body: None,
origin: url.clone(),
.. RequestInit::default()
});

*origin_header_clone.lock().unwrap() = None;
let response = fetch(request, None);
assert!(response.status.unwrap().is_success());

let _ = server.close();
}
Expand Up @@ -3,6 +3,3 @@
[Referer header]
expected: FAIL

[Origin header]
expected: FAIL

18 changes: 0 additions & 18 deletions tests/wpt/metadata/cors/allow-headers.htm.ini
@@ -1,14 +1,5 @@
[allow-headers.htm]
type: testharness
[Allow origin: *]
expected: FAIL

[Allow origin: _*__]
expected: FAIL

[Allow origin: [tab\]*]
expected: FAIL

[Allow origin: undefined//undefined]
expected: FAIL

Expand All @@ -21,15 +12,6 @@
[Allow origin: [tab\]undefined//undefined]
expected: FAIL

[Allow origin: http://web-platform.test:8000]
expected: FAIL

[Allow origin: _http://web-platform.test:8000]
expected: FAIL

[Allow origin: _http://web-platform.test:8000___[tab\]_]
expected: FAIL

[Allow origin: [tab\]http://web-platform.test:8000]
expected: FAIL

9 changes: 0 additions & 9 deletions tests/wpt/metadata/cors/basic.htm.ini
@@ -1,14 +1,5 @@
[basic.htm]
type: testharness
[Cross domain basic usage]
expected: FAIL

[Same domain different port]
expected: FAIL

[Cross domain different port]
expected: FAIL

[Cross domain different protocol]
expected: FAIL

Expand Down
12 changes: 4 additions & 8 deletions tests/wpt/metadata/cors/credentials-flag.htm.ini
@@ -1,12 +1,8 @@
[credentials-flag.htm]
type: testharness
expected: TIMEOUT
[Don't send cookie by default]
expected: TIMEOUT
[Access-Control-Allow-Credentials: True should be disallowed (async)]
expected: FAIL

[Don't send cookie part 2]
expected: TIMEOUT

[Don't obey Set-Cookie when withCredentials=false]
expected: TIMEOUT
[Access-Control-Allow-Credentials: TRUE should be disallowed (async)]
expected: FAIL

18 changes: 0 additions & 18 deletions tests/wpt/metadata/cors/origin.htm.ini
@@ -1,14 +1,5 @@
[origin.htm]
type: testharness
[Allow origin: *]
expected: FAIL

[Allow origin: _*__]
expected: FAIL

[Allow origin: [tab\]*]
expected: FAIL

[Allow origin: undefined//undefined]
expected: FAIL

Expand All @@ -21,15 +12,6 @@
[Allow origin: [tab\]undefined//undefined]
expected: FAIL

[Allow origin: http://web-platform.test:8000]
expected: FAIL

[Allow origin: _http://web-platform.test:8000]
expected: FAIL

[Allow origin: _http://web-platform.test:8000___[tab\]_]
expected: FAIL

[Allow origin: [tab\]http://web-platform.test:8000]
expected: FAIL

18 changes: 0 additions & 18 deletions tests/wpt/metadata/cors/redirect-origin.htm.ini
Expand Up @@ -56,24 +56,6 @@
[remote (undefined//undefined) to remote2 (null), expect origin=null]
expected: FAIL

[local (*) to remote (*), expect origin=http://web-platform.test:8000]
expected: FAIL

[local (*) to remote (http://web-platform.test:8000), expect origin=http://web-platform.test:8000]
expected: FAIL

[local (http://web-platform.test:8000) to remote (*), expect origin=http://web-platform.test:8000]
expected: FAIL

[local (http://web-platform.test:8000) to remote (http://web-platform.test:8000), expect origin=http://web-platform.test:8000]
expected: FAIL

[local (null) to remote (*), expect origin=http://web-platform.test:8000]
expected: FAIL

[local (none) to remote (*), expect origin=http://web-platform.test:8000]
expected: FAIL

[remote (http://web-platform.test:8000) to local (*), expect origin=null]
expected: FAIL

Expand Down
14 changes: 0 additions & 14 deletions tests/wpt/metadata/cors/request-headers.htm.ini

This file was deleted.

53 changes: 0 additions & 53 deletions tests/wpt/metadata/cors/status-async.htm.ini

This file was deleted.

50 changes: 0 additions & 50 deletions tests/wpt/metadata/cors/status-preflight.htm.ini

This file was deleted.

0 comments on commit a11a3fe

Please sign in to comment.