aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosh Matthews <josh@joshmatthews.net>2015-02-02 20:45:42 +0000
committerJosh Matthews <josh@joshmatthews.net>2015-02-04 13:37:01 +0000
commitfb217ab24b28f41526b8024fa3f4d6266e50e746 (patch)
treefef7bae6f70cedd44c6a564116048d8c9ee6b88a
parent542e8d52d586590872b4bf0148d3d25fbfa67555 (diff)
downloadservo-fb217ab24b28f41526b8024fa3f4d6266e50e746.tar.gz
servo-fb217ab24b28f41526b8024fa3f4d6266e50e746.zip
Make XMLHttpRequest user-set headers be preserved across redirects.
-rw-r--r--components/net/http_loader.rs19
-rw-r--r--components/net/resource_task.rs4
-rw-r--r--components/script/dom/xmlhttprequest.rs62
-rw-r--r--components/script/script_task.rs5
4 files changed, 49 insertions, 41 deletions
diff --git a/components/net/http_loader.rs b/components/net/http_loader.rs
index 95ecd161aff..f06323ac348 100644
--- a/components/net/http_loader.rs
+++ b/components/net/http_loader.rs
@@ -108,22 +108,29 @@ reason: \"certificate verify failed\" }]";
}
};
+ // Preserve the `host` header set automatically by Request.
+ let host = req.headers().get::<Host>().unwrap().clone();
+
// Avoid automatically preserving request headers when redirects occur.
// See https://bugzilla.mozilla.org/show_bug.cgi?id=401564 and
- // https://bugzilla.mozilla.org/show_bug.cgi?id=216828
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=216828 .
+ // Only preserve ones which have been explicitly marked as such.
if iters == 1 {
- // Preserve the `host` header set automatically by Request.
- let host = req.headers().get::<Host>().unwrap().clone();
- *req.headers_mut() = load_data.headers.clone();
- req.headers_mut().set(host);
+ let mut combined_headers = load_data.headers.clone();
+ combined_headers.extend(load_data.preserved_headers.iter());
+ *req.headers_mut() = combined_headers;
+ } else {
+ *req.headers_mut() = load_data.preserved_headers.clone();
}
+ req.headers_mut().set(host);
+
let (tx, rx) = channel();
cookies_chan.send(ControlMsg::GetCookiesForUrl(url.clone(), tx, CookieSource::HTTP));
if let Some(cookie_list) = rx.recv().unwrap() {
let mut v = Vec::new();
v.push(cookie_list.into_bytes());
- load_data.headers.set_raw("Cookie".to_owned(), v);
+ req.headers_mut().set_raw("Cookie".to_owned(), v);
}
// FIXME(seanmonstar): use AcceptEncoding from Hyper once available
diff --git a/components/net/resource_task.rs b/components/net/resource_task.rs
index cdd62c67abf..14aacc5d451 100644
--- a/components/net/resource_task.rs
+++ b/components/net/resource_task.rs
@@ -40,7 +40,10 @@ pub enum ControlMsg {
pub struct LoadData {
pub url: Url,
pub method: Method,
+ /// Headers that will apply to the initial request only
pub headers: Headers,
+ /// Headers that will apply to the initial request and any redirects
+ pub preserved_headers: Headers,
pub data: Option<Vec<u8>>,
pub cors: Option<ResourceCORSData>,
pub consumer: Sender<LoadResponse>,
@@ -52,6 +55,7 @@ impl LoadData {
url: url,
method: Method::Get,
headers: Headers::new(),
+ preserved_headers: Headers::new(),
data: None,
cors: None,
consumer: consumer,
diff --git a/components/script/dom/xmlhttprequest.rs b/components/script/dom/xmlhttprequest.rs
index a32045cff75..f9f75fbbf7e 100644
--- a/components/script/dom/xmlhttprequest.rs
+++ b/components/script/dom/xmlhttprequest.rs
@@ -561,41 +561,35 @@ impl<'a> XMLHttpRequestMethods for JSRef<'a, XMLHttpRequest> {
let mut load_data = LoadData::new(self.request_url.borrow().clone().unwrap(), start_chan);
load_data.data = extracted;
- // Default headers
- {
- #[inline]
- fn join_raw(a: &str, b: &str) -> Vec<u8> {
- let len = a.len() + b.len();
- let mut vec = Vec::with_capacity(len);
- vec.push_all(a.as_bytes());
- vec.push_all(b.as_bytes());
- vec
- }
- let ref mut request_headers = self.request_headers.borrow_mut();
- if !request_headers.has::<ContentType>() {
- // XHR spec differs from http, and says UTF-8 should be in capitals,
- // instead of "utf-8", which is what Hyper defaults to.
- let params = ";charset=UTF-8";
- let n = "content-type";
- match data {
- Some(eString(_)) =>
- request_headers.set_raw(n.to_owned(), vec![join_raw("text/plain", params)]),
- Some(eURLSearchParams(_)) =>
- request_headers.set_raw(
- n.to_owned(), vec![join_raw("application/x-www-form-urlencoded", params)]),
- None => ()
- }
- }
+ #[inline]
+ fn join_raw(a: &str, b: &str) -> Vec<u8> {
+ let len = a.len() + b.len();
+ let mut vec = Vec::with_capacity(len);
+ vec.push_all(a.as_bytes());
+ vec.push_all(b.as_bytes());
+ vec
+ }
+ // XHR spec differs from http, and says UTF-8 should be in capitals,
+ // instead of "utf-8", which is what Hyper defaults to.
+ let params = ";charset=UTF-8";
+ let n = "content-type";
+ match data {
+ Some(eString(_)) =>
+ load_data.headers.set_raw(n.to_owned(), vec![join_raw("text/plain", params)]),
+ Some(eURLSearchParams(_)) =>
+ load_data.headers.set_raw(
+ n.to_owned(), vec![join_raw("application/x-www-form-urlencoded", params)]),
+ None => ()
+ }
- if !request_headers.has::<Accept>() {
- let mime = Mime(mime::TopLevel::Star, mime::SubLevel::Star, vec![]);
- request_headers.set(
- Accept(vec![QualityItem::new(mime, 1.0)]));
- }
- } // drops the borrow_mut
+ load_data.preserved_headers = (*self.request_headers.borrow()).clone();
+
+ if !load_data.preserved_headers.has::<Accept>() {
+ let mime = Mime(mime::TopLevel::Star, mime::SubLevel::Star, vec![]);
+ load_data.preserved_headers.set(Accept(vec![QualityItem::new(mime, 1.0)]));
+ }
- load_data.headers = (*self.request_headers.borrow()).clone();
load_data.method = (*self.request_method.borrow()).clone();
let (terminate_sender, terminate_receiver) = channel();
*self.terminate_sender.borrow_mut() = Some(terminate_sender);
@@ -607,8 +601,10 @@ impl<'a> XMLHttpRequestMethods for JSRef<'a, XMLHttpRequest> {
} else {
RequestMode::CORS
};
+ let mut combined_headers = load_data.headers.clone();
+ combined_headers.extend(load_data.preserved_headers.iter());
let cors_request = CORSRequest::maybe_new(referer_url.clone(), load_data.url.clone(), mode,
- load_data.method.clone(), load_data.headers.clone());
+ load_data.method.clone(), combined_headers);
match cors_request {
Ok(None) => {
let mut buf = String::new();
diff --git a/components/script/script_task.rs b/components/script/script_task.rs
index d374cfcf9ba..71f34c9330f 100644
--- a/components/script/script_task.rs
+++ b/components/script/script_task.rs
@@ -67,7 +67,7 @@ use util::task::spawn_named_with_send_on_failure;
use util::task_state;
use geom::point::Point2D;
-use hyper::header::{Header, HeaderFormat};
+use hyper::header::{Header, Headers, HeaderFormat};
use hyper::header::shared::util as header_util;
use js::jsapi::{JS_SetWrapObjectCallbacks, JS_SetGCZeal, JS_DEFAULT_ZEAL_FREQ, JS_GC};
use js::jsapi::{JSContext, JSRuntime, JSObject};
@@ -795,7 +795,8 @@ impl ScriptTask {
self.resource_task.send(ControlMsg::Load(NetLoadData {
url: url,
method: load_data.method,
- headers: load_data.headers,
+ headers: Headers::new(),
+ preserved_headers: load_data.headers,
data: load_data.data,
cors: None,
consumer: input_chan,