diff options
author | Manish Goregaokar <manishsmail@gmail.com> | 2014-06-05 23:31:08 +0530 |
---|---|---|
committer | Manish Goregaokar <manishsmail@gmail.com> | 2014-06-06 16:10:54 +0530 |
commit | cfa20e9fba05c66be7471ee309d63e7d9fbba636 (patch) | |
tree | c77464bf84f3a858e2fa0c1af8a4bb73460f2d62 | |
parent | 10b1e655b0dfec66fea948f974d41339d796c716 (diff) | |
download | servo-cfa20e9fba05c66be7471ee309d63e7d9fbba636.tar.gz servo-cfa20e9fba05c66be7471ee309d63e7d9fbba636.zip |
JSON response support and some default headers
-rw-r--r-- | src/components/net/http_loader.rs | 5 | ||||
-rw-r--r-- | src/components/script/dom/webidls/XMLHttpRequest.webidl | 1 | ||||
-rw-r--r-- | src/components/script/dom/xmlhttprequest.rs | 98 |
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() + } } |