Auto merge of #15903 - servo:set-origin-header, r=Wafflespeanut

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 -->
This commit is contained in:
bors-servo 2017-03-09 22:15:11 -08:00 committed by GitHub
commit a11a3fe68b
16 changed files with 93 additions and 250 deletions

View file

@ -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;
@ -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,
@ -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

View file

@ -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};
@ -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;
@ -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,
@ -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();
}

View file

@ -3,6 +3,3 @@
[Referer header]
expected: FAIL
[Origin header]
expected: FAIL

View file

@ -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
@ -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

View file

@ -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

View file

@ -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

View file

@ -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
@ -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

View file

@ -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

View file

@ -1,14 +0,0 @@
[request-headers.htm]
type: testharness
[basic request header]
expected: FAIL
[Simple request headers need not be in allow-headers]
expected: FAIL
[Strange allowheaders (case insensitive)]
expected: FAIL
[INVALID_STATE_ERR on setRequestHeader after send()]
expected: FAIL

View file

@ -1,53 +0,0 @@
[status-async.htm]
type: testharness
[Status on GET 200]
expected: FAIL
[Status on GET 201]
expected: FAIL
[Status on GET 202]
expected: FAIL
[Status on GET 203]
expected: FAIL
[Status on GET 204]
expected: FAIL
[Status on GET 205]
expected: FAIL
[Status on GET 206]
expected: FAIL
[Status on GET 209]
expected: FAIL
[Status on GET 299]
expected: FAIL
[Status on POST 200]
expected: FAIL
[Status on HEAD 200]
expected: FAIL
[Status on PUT 200]
expected: FAIL
[Status on CHICKEN 200]
expected: FAIL
[Status on GET 400]
expected: FAIL
[Status on HEAD 401]
expected: FAIL
[Status on POST 404]
expected: FAIL
[Status on POST 500]
expected: FAIL

View file

@ -1,50 +0,0 @@
[status-preflight.htm]
type: testharness
[CORS - status after preflight on GET 200]
expected: FAIL
[CORS - status after preflight on GET 204]
expected: FAIL
[CORS - status after preflight on GET 400]
expected: FAIL
[CORS - status after preflight on GET 401]
expected: FAIL
[CORS - status after preflight on HEAD 200]
expected: FAIL
[CORS - status after preflight on HEAD 204]
expected: FAIL
[CORS - status after preflight on HEAD 400]
expected: FAIL
[CORS - status after preflight on HEAD 401]
expected: FAIL
[CORS - status after preflight on HEAD 501]
expected: FAIL
[CORS - status after preflight on HEAD 699]
expected: FAIL
[CORS - status after preflight on POST 204]
expected: FAIL
[CORS - status after preflight on POST 400]
expected: FAIL
[CORS - status after preflight on POST 401]
expected: FAIL
[CORS - status after preflight on POST 404]
expected: FAIL
[CORS - status after preflight on PUT 699]
expected: FAIL
[CORS - status after preflight on CHICKEN 501]
expected: FAIL

View file

@ -1,8 +0,0 @@
[status.htm]
type: testharness
[3. CORS allowed, response status 400.]
expected: FAIL
[4. CORS allowed, preflight status 200, response status 400.]
expected: FAIL

View file

@ -1,15 +1,9 @@
[eventsource-cross-origin.htm]
type: testharness
expected: TIMEOUT
[EventSource: cross-origin basic use]
expected: TIMEOUT
[EventSource: cross-origin redirect use]
expected: TIMEOUT
[EventSource: cross-origin redirect use recon]
expected: TIMEOUT
[EventSource: cross-origin allow-origin: http://example.org should fail]
expected: FAIL

View file

@ -1,6 +0,0 @@
[request-cache-control.htm]
type: testharness
expected: TIMEOUT
[EventSource: Cache-Control 1]
expected: TIMEOUT

View file

@ -1,12 +0,0 @@
[request-credentials.htm]
type: testharness
expected: TIMEOUT
[EventSource: credentials: credentials enabled]
expected: TIMEOUT
[EventSource: credentials: credentials disabled]
expected: TIMEOUT
[EventSource: credentials: credentials default]
expected: TIMEOUT

View file

@ -1,23 +1,14 @@
[request-headers.html]
type: testharness
[Fetch with PUT without body]
expected: FAIL
[Fetch with PUT with body]
expected: FAIL
[Fetch with POST without body]
expected: FAIL
[Fetch with POST with text body]
expected: FAIL
[Fetch with POST with FormData body]
expected: FAIL
[Fetch with POST with Blob body]
expected: FAIL
[Fetch with POST with ArrayBuffer body]
expected: FAIL
@ -48,15 +39,6 @@
[Fetch with POST with URLSearchParams body]
expected: FAIL
[Fetch with POST and mode "same-origin" needs an Origin header]
expected: FAIL
[Fetch with POST and mode "no-cors" needs an Origin header]
expected: FAIL
[Fetch with PUT and mode "same-origin" needs an Origin header]
expected: FAIL
[Fetch with TacO and mode "same-origin" needs an Origin header]
expected: FAIL