mirror of
https://github.com/servo/servo.git
synced 2025-08-06 06:00:15 +01:00
Support for extension methods, getResponseHeader(), and an extra error
This commit is contained in:
parent
1184b500e5
commit
e8de5f2f55
6 changed files with 51 additions and 27 deletions
|
@ -8,7 +8,7 @@ use dom::bindings::codegen::Bindings::XMLHttpRequestBinding::XMLHttpRequestRespo
|
|||
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};
|
||||
use dom::bindings::error::{ErrorResult, Fallible, InvalidState, InvalidAccess, Network, Syntax, Security};
|
||||
use dom::bindings::js::{JS, JSRef, Temporary, OptionalSettable, OptionalRootedRootable};
|
||||
use dom::bindings::str::ByteString;
|
||||
use dom::bindings::trace::Untraceable;
|
||||
|
@ -30,7 +30,7 @@ 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::method::{Method, Get, Head, Connect, Trace, ExtensionMethod};
|
||||
use http::status::Status;
|
||||
|
||||
use js::jsapi::{JS_AddObjectRoot, JS_ParseJSON, JS_RemoveObjectRoot, JSContext};
|
||||
|
@ -241,7 +241,7 @@ pub trait XMLHttpRequestMethods<'a> {
|
|||
fn ResponseURL(&self) -> DOMString;
|
||||
fn Status(&self) -> u16;
|
||||
fn StatusText(&self) -> ByteString;
|
||||
fn GetResponseHeader(&self, _name: ByteString) -> Option<ByteString>;
|
||||
fn GetResponseHeader(&self, name: ByteString) -> Option<ByteString>;
|
||||
fn GetAllResponseHeaders(&self) -> ByteString;
|
||||
fn OverrideMimeType(&self, _mime: DOMString);
|
||||
fn ResponseType(&self) -> XMLHttpRequestResponseType;
|
||||
|
@ -267,13 +267,30 @@ impl<'a> XMLHttpRequestMethods<'a> for JSRef<'a, XMLHttpRequest> {
|
|||
}
|
||||
|
||||
fn Open(&mut self, method: ByteString, url: DOMString) -> ErrorResult {
|
||||
let maybe_method: Option<Method> = method.as_str().and_then(|s| {
|
||||
FromStr::from_str(s.to_ascii_upper().as_slice()) // rust-http tests against the uppercase versions
|
||||
let uppercase_method = method.as_str().map(|s| {
|
||||
let upper = s.to_ascii_upper();
|
||||
match upper.as_slice() {
|
||||
"DELETE" | "GET" | "HEAD" | "OPTIONS" |
|
||||
"POST" | "PUT" | "CONNECT" | "TRACE" |
|
||||
"TRACK" => upper,
|
||||
_ => s.to_string()
|
||||
}
|
||||
});
|
||||
let maybe_method: Option<Method> = uppercase_method.and_then(|s| {
|
||||
// Note: rust-http tests against the uppercase versions
|
||||
// Since we want to pass methods not belonging to the short list above
|
||||
// without changing capitalization, this will actually sidestep rust-http's type system
|
||||
// since methods like "patch" or "PaTcH" will be considered extension methods
|
||||
// despite the there being a rust-http method variant for them
|
||||
Method::from_str_or_new(s.as_slice())
|
||||
});
|
||||
// Step 2
|
||||
let base: Option<Url> = Some(self.global.root().get_url());
|
||||
match maybe_method {
|
||||
Some(Get) | Some(Post) | Some(Head) => {
|
||||
// Step 4
|
||||
Some(Connect) | Some(Trace) => Err(Security),
|
||||
Some(ExtensionMethod(ref t)) if t.as_slice() == "TRACK" => Err(Security),
|
||||
Some(_) if method.is_token() => {
|
||||
|
||||
*self.request_method = maybe_method.unwrap();
|
||||
|
||||
|
@ -282,8 +299,14 @@ impl<'a> XMLHttpRequestMethods<'a> for JSRef<'a, XMLHttpRequest> {
|
|||
Ok(parsed) => parsed,
|
||||
Err(_) => return Err(Syntax) // Step 7
|
||||
};
|
||||
// XXXManishearth Do some handling of username/passwords, and abort existing requests
|
||||
|
||||
// XXXManishearth Do some handling of username/passwords
|
||||
if self.sync {
|
||||
// FIXME: This should only happen if the global environmet is a document environment
|
||||
if self.timeout != 0 || self.with_credentials || self.response_type != _empty {
|
||||
return Err(InvalidAccess)
|
||||
}
|
||||
}
|
||||
// XXXManishearth abort existing requests
|
||||
// Step 12
|
||||
*self.request_url = parsed_url;
|
||||
*self.request_headers = RequestHeaderCollection::new();
|
||||
|
@ -295,22 +318,9 @@ impl<'a> XMLHttpRequestMethods<'a> for JSRef<'a, XMLHttpRequest> {
|
|||
if self.ready_state != Opened {
|
||||
self.change_ready_state(Opened);
|
||||
}
|
||||
//XXXManishearth fire a progressevent
|
||||
Ok(())
|
||||
},
|
||||
// XXXManishearth Handle other standard methods
|
||||
Some(Connect) | Some(Trace) => {
|
||||
// XXXManishearth Track isn't in rust-http, but it should end up in this match arm.
|
||||
Err(Security) // Step 4
|
||||
},
|
||||
None => Err(Syntax), // Step 3
|
||||
_ => {
|
||||
if method.is_token() {
|
||||
Ok(()) // XXXManishearth handle extension methods
|
||||
} else {
|
||||
Err(Syntax) // Step 3
|
||||
}
|
||||
}
|
||||
_ => Err(Syntax), // Step 3
|
||||
}
|
||||
}
|
||||
fn Open_(&mut self, method: ByteString, url: DOMString, async: bool,
|
||||
|
@ -491,8 +501,12 @@ impl<'a> XMLHttpRequestMethods<'a> for JSRef<'a, XMLHttpRequest> {
|
|||
fn StatusText(&self) -> ByteString {
|
||||
self.status_text.clone()
|
||||
}
|
||||
fn GetResponseHeader(&self, _name: ByteString) -> Option<ByteString> {
|
||||
None
|
||||
fn GetResponseHeader(&self, name: ByteString) -> Option<ByteString> {
|
||||
self.response_headers.deref().iter().find(|h| {
|
||||
name.eq_ignore_case(&FromStr::from_str(h.header_name().as_slice()).unwrap())
|
||||
}).map(|h| {
|
||||
FromStr::from_str(h.header_value().as_slice()).unwrap()
|
||||
})
|
||||
}
|
||||
fn GetAllResponseHeaders(&self) -> ByteString {
|
||||
let mut writer = MemWriter::new();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue