aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorManish Goregaokar <manishsmail@gmail.com>2014-06-05 23:31:08 +0530
committerManish Goregaokar <manishsmail@gmail.com>2014-06-06 16:10:54 +0530
commitcfa20e9fba05c66be7471ee309d63e7d9fbba636 (patch)
treec77464bf84f3a858e2fa0c1af8a4bb73460f2d62
parent10b1e655b0dfec66fea948f974d41339d796c716 (diff)
downloadservo-cfa20e9fba05c66be7471ee309d63e7d9fbba636.tar.gz
servo-cfa20e9fba05c66be7471ee309d63e7d9fbba636.zip
JSON response support and some default headers
-rw-r--r--src/components/net/http_loader.rs5
-rw-r--r--src/components/script/dom/webidls/XMLHttpRequest.webidl1
-rw-r--r--src/components/script/dom/xmlhttprequest.rs98
3 files changed, 82 insertions, 22 deletions
diff --git a/src/components/net/http_loader.rs b/src/components/net/http_loader.rs
index dbf9f1d4660..7e954c87010 100644
--- a/src/components/net/http_loader.rs
+++ b/src/components/net/http_loader.rs
@@ -68,7 +68,10 @@ fn load(load_data: LoadData, start_chan: Sender<LoadResponse>) {
let host = writer.headers.host.clone();
writer.headers = box load_data.headers.clone();
writer.headers.host = host;
-
+ if writer.headers.accept_encoding.is_none() {
+ // We currently don't support HTTP Compression (FIXME #2587)
+ writer.headers.accept_encoding = Some(String::from_str("identity".as_slice()))
+ }
match load_data.data {
Some(ref data) => {
writer.headers.content_length = Some(data.len());
diff --git a/src/components/script/dom/webidls/XMLHttpRequest.webidl b/src/components/script/dom/webidls/XMLHttpRequest.webidl
index aebb32fbe4c..ab06165a098 100644
--- a/src/components/script/dom/webidls/XMLHttpRequest.webidl
+++ b/src/components/script/dom/webidls/XMLHttpRequest.webidl
@@ -59,6 +59,7 @@ interface XMLHttpRequest : XMLHttpRequestEventTarget {
// ByteString? getResponseHeader(ByteString name);
ByteString getAllResponseHeaders();
// void overrideMimeType(DOMString mime);
+ [SetterThrows]
attribute XMLHttpRequestResponseType responseType;
readonly attribute any response;
[Throws]
diff --git a/src/components/script/dom/xmlhttprequest.rs b/src/components/script/dom/xmlhttprequest.rs
index b5240e0536f..c3f2c95ea09 100644
--- a/src/components/script/dom/xmlhttprequest.rs
+++ b/src/components/script/dom/xmlhttprequest.rs
@@ -5,7 +5,7 @@
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
use dom::bindings::codegen::Bindings::XMLHttpRequestBinding;
use dom::bindings::codegen::Bindings::XMLHttpRequestBinding::XMLHttpRequestResponseType;
-use dom::bindings::codegen::Bindings::XMLHttpRequestBinding::XMLHttpRequestResponseTypeValues::{_empty, Text};
+use dom::bindings::codegen::Bindings::XMLHttpRequestBinding::XMLHttpRequestResponseTypeValues::{_empty, Json, Text};
use dom::bindings::codegen::InheritTypes::{EventCast, EventTargetCast, XMLHttpRequestDerived};
use dom::bindings::conversions::ToJSValConvertible;
use dom::bindings::error::{ErrorResult, Fallible, InvalidState, Network, Syntax, Security};
@@ -22,17 +22,19 @@ use dom::xmlhttprequesteventtarget::XMLHttpRequestEventTarget;
use dom::xmlhttprequestupload::XMLHttpRequestUpload;
use encoding::all::UTF_8;
+use encoding::label::encoding_from_whatwg_label;
use encoding::types::{DecodeReplace, Encoding};
use ResponseHeaderCollection = http::headers::response::HeaderCollection;
use RequestHeaderCollection = http::headers::request::HeaderCollection;
+use http::headers::content_type::MediaType;
use http::headers::{HeaderEnum, HeaderValueByteIterator};
use http::headers::request::Header;
use http::method::{Method, Get, Head, Post, Connect, Trace};
use http::status::Status;
-use js::jsapi::{JS_AddObjectRoot, JS_RemoveObjectRoot, JSContext};
-use js::jsval::{JSVal, NullValue};
+use js::jsapi::{JS_AddObjectRoot, JS_ParseJSON, JS_RemoveObjectRoot, JSContext};
+use js::jsval::{JSVal, NullValue, UndefinedValue};
use libc;
use libc::c_void;
@@ -243,7 +245,7 @@ pub trait XMLHttpRequestMethods<'a> {
fn GetAllResponseHeaders(&self) -> ByteString;
fn OverrideMimeType(&self, _mime: DOMString);
fn ResponseType(&self) -> XMLHttpRequestResponseType;
- fn SetResponseType(&mut self, response_type: XMLHttpRequestResponseType);
+ fn SetResponseType(&mut self, response_type: XMLHttpRequestResponseType) -> ErrorResult;
fn Response(&self, _cx: *mut JSContext) -> JSVal;
fn GetResponseText(&self) -> Fallible<DOMString>;
fn GetResponseXML(&self) -> Option<Temporary<Document>>;
@@ -434,9 +436,33 @@ impl<'a> XMLHttpRequestMethods<'a> for JSRef<'a, XMLHttpRequest> {
let mut load_data = LoadData::new((*self.request_url).clone());
load_data.data = data;
- // XXXManishearth deal with the Origin/Referer/Accept headers
- // XXXManishearth the below is only valid when content type is not already set by the user.
- self.insert_trusted_header("content-type".to_string(), "text/plain;charset=UTF-8".to_string());
+ // Default headers
+
+ if self.request_headers.content_type.is_none() {
+ self.request_headers.content_type = Some(MediaType {
+ type_: String::from_str("text"),
+ subtype: String::from_str("plain"),
+ parameters: vec!((String::from_str("charset"), String::from_str("UTF-8")))
+ });
+ }
+
+ if self.request_headers.accept.is_none() {
+ self.request_headers.accept = Some(String::from_str("*/*"))
+ }
+
+ // XXXManishearth this is to be replaced with Origin for CORS (with no path)
+ let referer_url = self.global.root().get_url();
+ let mut buf = String::new();
+ buf.push_str(referer_url.scheme.as_slice());
+ buf.push_str("://".as_slice());
+ buf.push_str(referer_url.host.as_slice());
+ referer_url.port.as_ref().map(|p| {
+ buf.push_str(":".as_slice());
+ buf.push_str(p.as_slice());
+ });
+ buf.push_str(referer_url.path.as_slice());
+ self.request_headers.referer = Some(buf);
+
load_data.headers = (*self.request_headers).clone();
load_data.method = (*self.request_method).clone();
if self.sync {
@@ -479,26 +505,41 @@ impl<'a> XMLHttpRequestMethods<'a> for JSRef<'a, XMLHttpRequest> {
fn ResponseType(&self) -> XMLHttpRequestResponseType {
self.response_type
}
- fn SetResponseType(&mut self, response_type: XMLHttpRequestResponseType) {
- self.response_type = response_type
+ fn SetResponseType(&mut self, response_type: XMLHttpRequestResponseType) -> ErrorResult {
+ if self.sync {
+ // FIXME: When Workers are implemented, there should be
+ // an additional check that this is a document environment
+ return Err(InvalidState);
+ }
+ match self.ready_state {
+ Loading | XHRDone => Err(InvalidState),
+ _ => {
+ self.response_type = response_type;
+ Ok(())
+ }
+ }
}
fn Response(&self, cx: *mut JSContext) -> JSVal {
match self.response_type {
_empty | Text => {
if self.ready_state == XHRDone || self.ready_state == Loading {
- self.response.to_jsval(cx)
+ self.text_response().to_jsval(cx)
} else {
"".to_string().to_jsval(cx)
}
},
- _ => {
- if self.ready_state == XHRDone {
- // XXXManishearth we may not be able to store
- // other response types as DOMStrings
- self.response.to_jsval(cx)
- } else {
- NullValue()
+ _ if self.ready_state != XHRDone => NullValue(),
+ Json => {
+ let decoded = UTF_8.decode(self.response.as_slice(), DecodeReplace).unwrap().to_string().to_utf16();
+ let mut vp = UndefinedValue();
+ unsafe {
+ JS_ParseJSON(cx, decoded.as_ptr(), decoded.len() as u32, &mut vp);
}
+ vp
+ }
+ _ => {
+ // XXXManishearth handle other response types
+ self.response.to_jsval(cx)
}
}
}
@@ -506,10 +547,7 @@ impl<'a> XMLHttpRequestMethods<'a> for JSRef<'a, XMLHttpRequest> {
match self.response_type {
_empty | Text => {
match self.ready_state {
- // XXXManishearth handle charset, etc (http://xhr.spec.whatwg.org/#text-response)
- // According to Simon decode() should never return an error, so unwrap()ing
- // the result should be fine. XXXManishearth have a closer look at this later
- Loading | XHRDone => Ok(UTF_8.decode(self.response.as_slice(), DecodeReplace).unwrap().to_string()),
+ Loading | XHRDone => Ok(self.text_response()),
_ => Ok("".to_string())
}
},
@@ -560,6 +598,7 @@ trait PrivateXMLHttpRequestHelpers {
fn dispatch_progress_event(&self, upload: bool, type_: DOMString, loaded: u64, total: Option<u64>);
fn dispatch_upload_progress_event(&self, type_: DOMString, partial_load: Option<u64>);
fn dispatch_response_progress_event(&self, type_: DOMString);
+ fn text_response(&self) -> DOMString;
}
impl<'a> PrivateXMLHttpRequestHelpers for JSRef<'a, XMLHttpRequest> {
@@ -708,4 +747,21 @@ impl<'a> PrivateXMLHttpRequestHelpers for JSRef<'a, XMLHttpRequest> {
let total = self.response_headers.deref().content_length.map(|x| {x as u64});
self.dispatch_progress_event(false, type_, len, total);
}
+
+ fn text_response(&self) -> DOMString {
+ let mut encoding = UTF_8 as &Encoding:Send;
+ match self.response_headers.content_type {
+ Some(ref x) => {
+ for &(ref name, ref value) in x.parameters.iter() {
+ if name.as_slice().eq_ignore_ascii_case("charset") {
+ encoding = encoding_from_whatwg_label(value.as_slice()).unwrap_or(encoding);
+ }
+ }
+ },
+ None => {}
+ }
+ // According to Simon, decode() should never return an error, so unwrap()ing
+ // the result should be fine. XXXManishearth have a closer look at this later
+ encoding.decode(self.response.as_slice(), DecodeReplace).unwrap().to_owned()
+ }
}