mirror of
https://github.com/servo/servo.git
synced 2025-08-05 21:50:18 +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
|
@ -2622,7 +2622,7 @@ use js::jsapi::JSContext;
|
|||
use js::jsval::JSVal;
|
||||
|
||||
#[repr(uint)]
|
||||
#[deriving(Encodable)]
|
||||
#[deriving(Encodable, Eq)]
|
||||
pub enum valuelist {
|
||||
%s
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ pub enum Error {
|
|||
InvalidState,
|
||||
Syntax,
|
||||
NamespaceError,
|
||||
InvalidAccess,
|
||||
Security,
|
||||
Network
|
||||
}
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use std::from_str::FromStr;
|
||||
use std::hash::{Hash, sip};
|
||||
use std::path::BytesContainer;
|
||||
use std::str;
|
||||
|
||||
#[deriving(Encodable,Clone,TotalEq,Eq)]
|
||||
|
@ -114,3 +116,9 @@ impl Hash for ByteString {
|
|||
vec.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for ByteString {
|
||||
fn from_str(s: &str) -> Option<ByteString> {
|
||||
Some(ByteString::new(s.container_into_owned_bytes()))
|
||||
}
|
||||
}
|
|
@ -46,8 +46,9 @@ impl DOMErrorName {
|
|||
error::InvalidCharacter => InvalidCharacterError,
|
||||
error::NotSupported => NotSupportedError,
|
||||
error::InvalidState => InvalidStateError,
|
||||
error::NamespaceError => NamespaceError,
|
||||
error::Syntax => SyntaxError,
|
||||
error::NamespaceError => NamespaceError,
|
||||
error::InvalidAccess => InvalidAccessError,
|
||||
error::Security => SecurityError,
|
||||
error::Network => NetworkError,
|
||||
error::FailureUnknown => fail!(),
|
||||
|
|
|
@ -56,7 +56,7 @@ interface XMLHttpRequest : XMLHttpRequestEventTarget {
|
|||
readonly attribute DOMString responseURL;
|
||||
readonly attribute unsigned short status;
|
||||
readonly attribute ByteString statusText;
|
||||
// ByteString? getResponseHeader(ByteString name);
|
||||
ByteString? getResponseHeader(ByteString name);
|
||||
ByteString getAllResponseHeaders();
|
||||
// void overrideMimeType(DOMString mime);
|
||||
[SetterThrows]
|
||||
|
|
|
@ -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