servo: Merge #15903 - Set Origin header in http_network_or_cache_fetch (from servo:set-origin-header); r=Wafflespeanut

Source-Repo: https://github.com/servo/servo
Source-Revision: a11a3fe68bad97970568f7d785a41bd00b707e92

--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : a21445cd2ebf1eba3752ed0be5c48f48b3b46cb1
This commit is contained in:
Sam Giles 2017-03-09 22:15:11 -08:00
parent 49d319b27e
commit aaf9f3b7ae
2 changed files with 89 additions and 9 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();
}