mirror of
https://github.com/servo/servo.git
synced 2025-07-24 15:50:21 +01:00
Make XMLHttpRequest user-set headers be preserved across redirects.
This commit is contained in:
parent
542e8d52d5
commit
fb217ab24b
4 changed files with 49 additions and 41 deletions
|
@ -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.
|
// Avoid automatically preserving request headers when redirects occur.
|
||||||
// See https://bugzilla.mozilla.org/show_bug.cgi?id=401564 and
|
// 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 {
|
if iters == 1 {
|
||||||
// Preserve the `host` header set automatically by Request.
|
let mut combined_headers = load_data.headers.clone();
|
||||||
let host = req.headers().get::<Host>().unwrap().clone();
|
combined_headers.extend(load_data.preserved_headers.iter());
|
||||||
*req.headers_mut() = load_data.headers.clone();
|
*req.headers_mut() = combined_headers;
|
||||||
req.headers_mut().set(host);
|
} else {
|
||||||
|
*req.headers_mut() = load_data.preserved_headers.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
req.headers_mut().set(host);
|
||||||
|
|
||||||
let (tx, rx) = channel();
|
let (tx, rx) = channel();
|
||||||
cookies_chan.send(ControlMsg::GetCookiesForUrl(url.clone(), tx, CookieSource::HTTP));
|
cookies_chan.send(ControlMsg::GetCookiesForUrl(url.clone(), tx, CookieSource::HTTP));
|
||||||
if let Some(cookie_list) = rx.recv().unwrap() {
|
if let Some(cookie_list) = rx.recv().unwrap() {
|
||||||
let mut v = Vec::new();
|
let mut v = Vec::new();
|
||||||
v.push(cookie_list.into_bytes());
|
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
|
// FIXME(seanmonstar): use AcceptEncoding from Hyper once available
|
||||||
|
|
|
@ -40,7 +40,10 @@ pub enum ControlMsg {
|
||||||
pub struct LoadData {
|
pub struct LoadData {
|
||||||
pub url: Url,
|
pub url: Url,
|
||||||
pub method: Method,
|
pub method: Method,
|
||||||
|
/// Headers that will apply to the initial request only
|
||||||
pub headers: Headers,
|
pub headers: Headers,
|
||||||
|
/// Headers that will apply to the initial request and any redirects
|
||||||
|
pub preserved_headers: Headers,
|
||||||
pub data: Option<Vec<u8>>,
|
pub data: Option<Vec<u8>>,
|
||||||
pub cors: Option<ResourceCORSData>,
|
pub cors: Option<ResourceCORSData>,
|
||||||
pub consumer: Sender<LoadResponse>,
|
pub consumer: Sender<LoadResponse>,
|
||||||
|
@ -52,6 +55,7 @@ impl LoadData {
|
||||||
url: url,
|
url: url,
|
||||||
method: Method::Get,
|
method: Method::Get,
|
||||||
headers: Headers::new(),
|
headers: Headers::new(),
|
||||||
|
preserved_headers: Headers::new(),
|
||||||
data: None,
|
data: None,
|
||||||
cors: None,
|
cors: None,
|
||||||
consumer: consumer,
|
consumer: consumer,
|
||||||
|
|
|
@ -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);
|
let mut load_data = LoadData::new(self.request_url.borrow().clone().unwrap(), start_chan);
|
||||||
load_data.data = extracted;
|
load_data.data = extracted;
|
||||||
|
|
||||||
// Default headers
|
#[inline]
|
||||||
{
|
fn join_raw(a: &str, b: &str) -> Vec<u8> {
|
||||||
#[inline]
|
let len = a.len() + b.len();
|
||||||
fn join_raw(a: &str, b: &str) -> Vec<u8> {
|
let mut vec = Vec::with_capacity(len);
|
||||||
let len = a.len() + b.len();
|
vec.push_all(a.as_bytes());
|
||||||
let mut vec = Vec::with_capacity(len);
|
vec.push_all(b.as_bytes());
|
||||||
vec.push_all(a.as_bytes());
|
vec
|
||||||
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 => ()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// 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>() {
|
load_data.preserved_headers = (*self.request_headers.borrow()).clone();
|
||||||
let mime = Mime(mime::TopLevel::Star, mime::SubLevel::Star, vec![]);
|
|
||||||
request_headers.set(
|
if !load_data.preserved_headers.has::<Accept>() {
|
||||||
Accept(vec![QualityItem::new(mime, 1.0)]));
|
let mime = Mime(mime::TopLevel::Star, mime::SubLevel::Star, vec![]);
|
||||||
}
|
load_data.preserved_headers.set(Accept(vec![QualityItem::new(mime, 1.0)]));
|
||||||
} // drops the borrow_mut
|
}
|
||||||
|
|
||||||
load_data.headers = (*self.request_headers.borrow()).clone();
|
|
||||||
load_data.method = (*self.request_method.borrow()).clone();
|
load_data.method = (*self.request_method.borrow()).clone();
|
||||||
let (terminate_sender, terminate_receiver) = channel();
|
let (terminate_sender, terminate_receiver) = channel();
|
||||||
*self.terminate_sender.borrow_mut() = Some(terminate_sender);
|
*self.terminate_sender.borrow_mut() = Some(terminate_sender);
|
||||||
|
@ -607,8 +601,10 @@ impl<'a> XMLHttpRequestMethods for JSRef<'a, XMLHttpRequest> {
|
||||||
} else {
|
} else {
|
||||||
RequestMode::CORS
|
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,
|
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 {
|
match cors_request {
|
||||||
Ok(None) => {
|
Ok(None) => {
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
|
|
|
@ -67,7 +67,7 @@ use util::task::spawn_named_with_send_on_failure;
|
||||||
use util::task_state;
|
use util::task_state;
|
||||||
|
|
||||||
use geom::point::Point2D;
|
use geom::point::Point2D;
|
||||||
use hyper::header::{Header, HeaderFormat};
|
use hyper::header::{Header, Headers, HeaderFormat};
|
||||||
use hyper::header::shared::util as header_util;
|
use hyper::header::shared::util as header_util;
|
||||||
use js::jsapi::{JS_SetWrapObjectCallbacks, JS_SetGCZeal, JS_DEFAULT_ZEAL_FREQ, JS_GC};
|
use js::jsapi::{JS_SetWrapObjectCallbacks, JS_SetGCZeal, JS_DEFAULT_ZEAL_FREQ, JS_GC};
|
||||||
use js::jsapi::{JSContext, JSRuntime, JSObject};
|
use js::jsapi::{JSContext, JSRuntime, JSObject};
|
||||||
|
@ -795,7 +795,8 @@ impl ScriptTask {
|
||||||
self.resource_task.send(ControlMsg::Load(NetLoadData {
|
self.resource_task.send(ControlMsg::Load(NetLoadData {
|
||||||
url: url,
|
url: url,
|
||||||
method: load_data.method,
|
method: load_data.method,
|
||||||
headers: load_data.headers,
|
headers: Headers::new(),
|
||||||
|
preserved_headers: load_data.headers,
|
||||||
data: load_data.data,
|
data: load_data.data,
|
||||||
cors: None,
|
cors: None,
|
||||||
consumer: input_chan,
|
consumer: input_chan,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue