mirror of
https://github.com/servo/servo.git
synced 2025-07-23 07:13:52 +01:00
dom::Response implementation
This commit is contained in:
parent
569599d404
commit
faf32a7cfb
30 changed files with 402 additions and 124 deletions
|
@ -11,6 +11,7 @@ path = "lib.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
devtools_traits = {path = "../devtools_traits"}
|
devtools_traits = {path = "../devtools_traits"}
|
||||||
|
encoding = "0.2"
|
||||||
hyper = "0.9.9"
|
hyper = "0.9.9"
|
||||||
hyper_serde = "0.1.4"
|
hyper_serde = "0.1.4"
|
||||||
ipc-channel = "0.5"
|
ipc-channel = "0.5"
|
||||||
|
|
|
@ -11,12 +11,15 @@ extern crate hyper;
|
||||||
use actor::{Actor, ActorMessageStatus, ActorRegistry};
|
use actor::{Actor, ActorMessageStatus, ActorRegistry};
|
||||||
use devtools_traits::HttpRequest as DevtoolsHttpRequest;
|
use devtools_traits::HttpRequest as DevtoolsHttpRequest;
|
||||||
use devtools_traits::HttpResponse as DevtoolsHttpResponse;
|
use devtools_traits::HttpResponse as DevtoolsHttpResponse;
|
||||||
|
use encoding::all::UTF_8;
|
||||||
|
use encoding::types::{DecoderTrap, Encoding};
|
||||||
use hyper::header::Headers;
|
use hyper::header::Headers;
|
||||||
use hyper::header::{ContentType, Cookie};
|
use hyper::header::{ContentType, Cookie};
|
||||||
use hyper::http::RawStatus;
|
use hyper::http::RawStatus;
|
||||||
use hyper::method::Method;
|
use hyper::method::Method;
|
||||||
use protocol::JsonPacketStream;
|
use protocol::JsonPacketStream;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
use std::borrow::Cow;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::net::TcpStream;
|
use std::net::TcpStream;
|
||||||
use time;
|
use time;
|
||||||
|
@ -360,7 +363,10 @@ impl NetworkEventActor {
|
||||||
|
|
||||||
pub fn add_response(&mut self, response: DevtoolsHttpResponse) {
|
pub fn add_response(&mut self, response: DevtoolsHttpResponse) {
|
||||||
self.response.headers = response.headers.clone();
|
self.response.headers = response.headers.clone();
|
||||||
self.response.status = response.status.clone();
|
self.response.status = response.status.as_ref().map(|&(s, ref st)| {
|
||||||
|
let status_text = UTF_8.decode(st, DecoderTrap::Replace).unwrap();
|
||||||
|
RawStatus(s, Cow::from(status_text))
|
||||||
|
});
|
||||||
self.response.body = response.body.clone();
|
self.response.body = response.body.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#![deny(unsafe_code)]
|
#![deny(unsafe_code)]
|
||||||
|
|
||||||
extern crate devtools_traits;
|
extern crate devtools_traits;
|
||||||
|
extern crate encoding;
|
||||||
extern crate hyper;
|
extern crate hyper;
|
||||||
extern crate ipc_channel;
|
extern crate ipc_channel;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
|
|
@ -27,7 +27,6 @@ extern crate time;
|
||||||
extern crate url;
|
extern crate url;
|
||||||
|
|
||||||
use hyper::header::Headers;
|
use hyper::header::Headers;
|
||||||
use hyper::http::RawStatus;
|
|
||||||
use hyper::method::Method;
|
use hyper::method::Method;
|
||||||
use ipc_channel::ipc::IpcSender;
|
use ipc_channel::ipc::IpcSender;
|
||||||
use msg::constellation_msg::PipelineId;
|
use msg::constellation_msg::PipelineId;
|
||||||
|
@ -304,7 +303,7 @@ pub struct HttpRequest {
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct HttpResponse {
|
pub struct HttpResponse {
|
||||||
pub headers: Option<Headers>,
|
pub headers: Option<Headers>,
|
||||||
pub status: Option<RawStatus>,
|
pub status: Option<(u16, Vec<u8>)>,
|
||||||
pub body: Option<Vec<u8>>,
|
pub body: Option<Vec<u8>>,
|
||||||
pub pipeline_id: PipelineId,
|
pub pipeline_id: PipelineId,
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
|
|
||||||
use file_loader;
|
use file_loader;
|
||||||
use hyper::header::ContentType;
|
use hyper::header::ContentType;
|
||||||
use hyper::http::RawStatus;
|
|
||||||
use hyper::mime::{Mime, SubLevel, TopLevel};
|
use hyper::mime::{Mime, SubLevel, TopLevel};
|
||||||
use hyper_serde::Serde;
|
use hyper_serde::Serde;
|
||||||
use mime_classifier::MimeClassifier;
|
use mime_classifier::MimeClassifier;
|
||||||
|
@ -38,7 +37,7 @@ pub fn factory(mut load_data: LoadData,
|
||||||
Some(Serde(ContentType(Mime(TopLevel::Text, SubLevel::Html, vec![])))),
|
Some(Serde(ContentType(Mime(TopLevel::Text, SubLevel::Html, vec![])))),
|
||||||
charset: Some("utf-8".to_owned()),
|
charset: Some("utf-8".to_owned()),
|
||||||
headers: None,
|
headers: None,
|
||||||
status: Some(Serde(RawStatus(200, "OK".into()))),
|
status: Some((200, b"OK".to_vec())),
|
||||||
https_state: HttpsState::None,
|
https_state: HttpsState::None,
|
||||||
referrer: None,
|
referrer: None,
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
use filemanager_thread::{FileManager, UIProvider};
|
use filemanager_thread::{FileManager, UIProvider};
|
||||||
use hyper::header::{DispositionType, ContentDisposition, DispositionParam};
|
use hyper::header::{DispositionType, ContentDisposition, DispositionParam};
|
||||||
use hyper::header::{Headers, ContentType, ContentLength, Charset};
|
use hyper::header::{Headers, ContentType, ContentLength, Charset};
|
||||||
use hyper::http::RawStatus;
|
|
||||||
use hyper_serde::Serde;
|
use hyper_serde::Serde;
|
||||||
use ipc_channel::ipc;
|
use ipc_channel::ipc;
|
||||||
use mime::{Mime, Attr};
|
use mime::{Mime, Attr};
|
||||||
|
@ -72,7 +71,7 @@ fn load_blob<UI: 'static + UIProvider>
|
||||||
charset: charset.map(|c| c.as_str().to_string()),
|
charset: charset.map(|c| c.as_str().to_string()),
|
||||||
headers: Some(Serde(headers)),
|
headers: Some(Serde(headers)),
|
||||||
// https://w3c.github.io/FileAPI/#TwoHundredOK
|
// https://w3c.github.io/FileAPI/#TwoHundredOK
|
||||||
status: Some(Serde(RawStatus(200, "OK".into()))),
|
status: Some((200, b"OK".to_vec())),
|
||||||
https_state: HttpsState::None,
|
https_state: HttpsState::None,
|
||||||
referrer: None,
|
referrer: None,
|
||||||
};
|
};
|
||||||
|
|
|
@ -973,8 +973,9 @@ fn http_network_fetch(request: Rc<Request>,
|
||||||
Ok((res, msg)) => {
|
Ok((res, msg)) => {
|
||||||
response.url = Some(url.clone());
|
response.url = Some(url.clone());
|
||||||
response.status = Some(res.response.status);
|
response.status = Some(res.response.status);
|
||||||
response.raw_status = Some(res.response.status_raw().clone());
|
response.raw_status = Some((res.response.status_raw().0,
|
||||||
response.headers = res.response.headers.clone();
|
res.response.status_raw().1.as_bytes().to_vec()));
|
||||||
|
response.headers = res.response.headers.clone();
|
||||||
|
|
||||||
let res_body = response.body.clone();
|
let res_body = response.body.clone();
|
||||||
|
|
||||||
|
@ -1001,7 +1002,7 @@ fn http_network_fetch(request: Rc<Request>,
|
||||||
send_response_to_devtools(
|
send_response_to_devtools(
|
||||||
&sender, request_id.unwrap(),
|
&sender, request_id.unwrap(),
|
||||||
meta_headers.map(Serde::into_inner),
|
meta_headers.map(Serde::into_inner),
|
||||||
meta_status.map(Serde::into_inner),
|
meta_status,
|
||||||
pipeline_id);
|
pipeline_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -629,7 +629,7 @@ pub fn send_request_to_devtools(msg: ChromeToDevtoolsControlMsg,
|
||||||
pub fn send_response_to_devtools(devtools_chan: &Sender<DevtoolsControlMsg>,
|
pub fn send_response_to_devtools(devtools_chan: &Sender<DevtoolsControlMsg>,
|
||||||
request_id: String,
|
request_id: String,
|
||||||
headers: Option<Headers>,
|
headers: Option<Headers>,
|
||||||
status: Option<RawStatus>,
|
status: Option<(u16, Vec<u8>)>,
|
||||||
pipeline_id: PipelineId) {
|
pipeline_id: PipelineId) {
|
||||||
let response = DevtoolsHttpResponse { headers: headers, status: status, body: None, pipeline_id: pipeline_id };
|
let response = DevtoolsHttpResponse { headers: headers, status: status, body: None, pipeline_id: pipeline_id };
|
||||||
let net_event_response = NetworkEvent::HttpResponse(response);
|
let net_event_response = NetworkEvent::HttpResponse(response);
|
||||||
|
@ -1081,7 +1081,8 @@ pub fn load<A, B>(load_data: &LoadData,
|
||||||
None => None
|
None => None
|
||||||
});
|
});
|
||||||
metadata.headers = Some(Serde(adjusted_headers));
|
metadata.headers = Some(Serde(adjusted_headers));
|
||||||
metadata.status = Some(Serde(response.status_raw().clone()));
|
metadata.status = Some((response.status_raw().0,
|
||||||
|
response.status_raw().1.as_bytes().to_vec()));
|
||||||
metadata.https_state = if doc_url.scheme() == "https" {
|
metadata.https_state = if doc_url.scheme() == "https" {
|
||||||
HttpsState::Modern
|
HttpsState::Modern
|
||||||
} else {
|
} else {
|
||||||
|
@ -1097,7 +1098,7 @@ pub fn load<A, B>(load_data: &LoadData,
|
||||||
send_response_to_devtools(
|
send_response_to_devtools(
|
||||||
&chan, request_id.unwrap(),
|
&chan, request_id.unwrap(),
|
||||||
metadata.headers.clone().map(Serde::into_inner),
|
metadata.headers.clone().map(Serde::into_inner),
|
||||||
metadata.status.clone().map(Serde::into_inner),
|
metadata.status.clone(),
|
||||||
pipeline_id);
|
pipeline_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -560,9 +560,8 @@ pub struct Metadata {
|
||||||
/// Headers
|
/// Headers
|
||||||
pub headers: Option<Serde<Headers>>,
|
pub headers: Option<Serde<Headers>>,
|
||||||
|
|
||||||
#[ignore_heap_size_of = "Defined in hyper"]
|
|
||||||
/// HTTP Status
|
/// HTTP Status
|
||||||
pub status: Option<Serde<RawStatus>>,
|
pub status: Option<(u16, Vec<u8>)>,
|
||||||
|
|
||||||
/// Is successful HTTPS connection
|
/// Is successful HTTPS connection
|
||||||
pub https_state: HttpsState,
|
pub https_state: HttpsState,
|
||||||
|
@ -580,7 +579,7 @@ impl Metadata {
|
||||||
charset: None,
|
charset: None,
|
||||||
headers: None,
|
headers: None,
|
||||||
// https://fetch.spec.whatwg.org/#concept-response-status-message
|
// https://fetch.spec.whatwg.org/#concept-response-status-message
|
||||||
status: Some(Serde(RawStatus(200, "OK".into()))),
|
status: Some((200, b"OK".to_vec())),
|
||||||
https_state: HttpsState::None,
|
https_state: HttpsState::None,
|
||||||
referrer: None,
|
referrer: None,
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
//! The [Response](https://fetch.spec.whatwg.org/#responses) object
|
//! The [Response](https://fetch.spec.whatwg.org/#responses) object
|
||||||
//! resulting from a [fetch operation](https://fetch.spec.whatwg.org/#concept-fetch)
|
//! resulting from a [fetch operation](https://fetch.spec.whatwg.org/#concept-fetch)
|
||||||
use hyper::header::{AccessControlExposeHeaders, ContentType, Headers};
|
use hyper::header::{AccessControlExposeHeaders, ContentType, Headers};
|
||||||
use hyper::http::RawStatus;
|
|
||||||
use hyper::status::StatusCode;
|
use hyper::status::StatusCode;
|
||||||
use hyper_serde::Serde;
|
use hyper_serde::Serde;
|
||||||
use std::ascii::AsciiExt;
|
use std::ascii::AsciiExt;
|
||||||
|
@ -15,7 +14,7 @@ use url::Url;
|
||||||
use {Metadata, NetworkError};
|
use {Metadata, NetworkError};
|
||||||
|
|
||||||
/// [Response type](https://fetch.spec.whatwg.org/#concept-response-type)
|
/// [Response type](https://fetch.spec.whatwg.org/#concept-response-type)
|
||||||
#[derive(Clone, PartialEq, Copy, Debug, Deserialize, Serialize)]
|
#[derive(Clone, PartialEq, Copy, Debug, Deserialize, Serialize, HeapSizeOf)]
|
||||||
pub enum ResponseType {
|
pub enum ResponseType {
|
||||||
Basic,
|
Basic,
|
||||||
CORS,
|
CORS,
|
||||||
|
@ -26,7 +25,7 @@ pub enum ResponseType {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// [Response termination reason](https://fetch.spec.whatwg.org/#concept-response-termination-reason)
|
/// [Response termination reason](https://fetch.spec.whatwg.org/#concept-response-termination-reason)
|
||||||
#[derive(Clone, Copy, Deserialize, Serialize)]
|
#[derive(Clone, Copy, Deserialize, Serialize, HeapSizeOf)]
|
||||||
pub enum TerminationReason {
|
pub enum TerminationReason {
|
||||||
EndUserAbort,
|
EndUserAbort,
|
||||||
Fatal,
|
Fatal,
|
||||||
|
@ -35,7 +34,7 @@ pub enum TerminationReason {
|
||||||
|
|
||||||
/// The response body can still be pushed to after fetch
|
/// The response body can still be pushed to after fetch
|
||||||
/// This provides a way to store unfinished response bodies
|
/// This provides a way to store unfinished response bodies
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq, HeapSizeOf)]
|
||||||
pub enum ResponseBody {
|
pub enum ResponseBody {
|
||||||
Empty, // XXXManishearth is this necessary, or is Done(vec![]) enough?
|
Empty, // XXXManishearth is this necessary, or is Done(vec![]) enough?
|
||||||
Receiving(Vec<u8>),
|
Receiving(Vec<u8>),
|
||||||
|
@ -53,7 +52,7 @@ impl ResponseBody {
|
||||||
|
|
||||||
|
|
||||||
/// [Cache state](https://fetch.spec.whatwg.org/#concept-response-cache-state)
|
/// [Cache state](https://fetch.spec.whatwg.org/#concept-response-cache-state)
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Deserialize, Serialize, HeapSizeOf)]
|
||||||
pub enum CacheState {
|
pub enum CacheState {
|
||||||
None,
|
None,
|
||||||
Local,
|
Local,
|
||||||
|
@ -76,16 +75,19 @@ pub enum ResponseMsg {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A [Response](https://fetch.spec.whatwg.org/#concept-response) as defined by the Fetch spec
|
/// A [Response](https://fetch.spec.whatwg.org/#concept-response) as defined by the Fetch spec
|
||||||
#[derive(Clone)]
|
#[derive(Clone, HeapSizeOf)]
|
||||||
pub struct Response {
|
pub struct Response {
|
||||||
pub response_type: ResponseType,
|
pub response_type: ResponseType,
|
||||||
pub termination_reason: Option<TerminationReason>,
|
pub termination_reason: Option<TerminationReason>,
|
||||||
pub url: Option<Url>,
|
pub url: Option<Url>,
|
||||||
pub url_list: RefCell<Vec<Url>>,
|
pub url_list: RefCell<Vec<Url>>,
|
||||||
/// `None` can be considered a StatusCode of `0`.
|
/// `None` can be considered a StatusCode of `0`.
|
||||||
|
#[ignore_heap_size_of = "Defined in hyper"]
|
||||||
pub status: Option<StatusCode>,
|
pub status: Option<StatusCode>,
|
||||||
pub raw_status: Option<RawStatus>,
|
pub raw_status: Option<(u16, Vec<u8>)>,
|
||||||
|
#[ignore_heap_size_of = "Defined in hyper"]
|
||||||
pub headers: Headers,
|
pub headers: Headers,
|
||||||
|
#[ignore_heap_size_of = "Mutex heap size undefined"]
|
||||||
pub body: Arc<Mutex<ResponseBody>>,
|
pub body: Arc<Mutex<ResponseBody>>,
|
||||||
pub cache_state: CacheState,
|
pub cache_state: CacheState,
|
||||||
pub https_state: HttpsState,
|
pub https_state: HttpsState,
|
||||||
|
@ -104,7 +106,7 @@ impl Response {
|
||||||
url: None,
|
url: None,
|
||||||
url_list: RefCell::new(Vec::new()),
|
url_list: RefCell::new(Vec::new()),
|
||||||
status: Some(StatusCode::Ok),
|
status: Some(StatusCode::Ok),
|
||||||
raw_status: Some(RawStatus(200, "OK".into())),
|
raw_status: Some((200, b"OK".to_vec())),
|
||||||
headers: Headers::new(),
|
headers: Headers::new(),
|
||||||
body: Arc::new(Mutex::new(ResponseBody::Empty)),
|
body: Arc::new(Mutex::new(ResponseBody::Empty)),
|
||||||
cache_state: CacheState::None,
|
cache_state: CacheState::None,
|
||||||
|
@ -239,7 +241,7 @@ impl Response {
|
||||||
None => None
|
None => None
|
||||||
});
|
});
|
||||||
metadata.headers = Some(Serde(self.headers.clone()));
|
metadata.headers = Some(Serde(self.headers.clone()));
|
||||||
metadata.status = self.raw_status.clone().map(Serde);
|
metadata.status = self.raw_status.clone();
|
||||||
metadata.https_state = self.https_state;
|
metadata.https_state = self.https_state;
|
||||||
return Ok(metadata);
|
return Ok(metadata);
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,6 +50,7 @@ use html5ever::tree_builder::QuirksMode;
|
||||||
use hyper::header::Headers;
|
use hyper::header::Headers;
|
||||||
use hyper::method::Method;
|
use hyper::method::Method;
|
||||||
use hyper::mime::Mime;
|
use hyper::mime::Mime;
|
||||||
|
use hyper::status::StatusCode;
|
||||||
use ipc_channel::ipc::{IpcReceiver, IpcSender};
|
use ipc_channel::ipc::{IpcReceiver, IpcSender};
|
||||||
use js::glue::{CallObjectTracer, CallUnbarrieredObjectTracer, CallValueTracer};
|
use js::glue::{CallObjectTracer, CallUnbarrieredObjectTracer, CallValueTracer};
|
||||||
use js::jsapi::{GCTraceKindToAscii, Heap, TraceKind, JSObject, JSTracer};
|
use js::jsapi::{GCTraceKindToAscii, Heap, TraceKind, JSObject, JSTracer};
|
||||||
|
@ -62,6 +63,7 @@ use net_traits::image::base::{Image, ImageMetadata};
|
||||||
use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheThread};
|
use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheThread};
|
||||||
use net_traits::request::Request;
|
use net_traits::request::Request;
|
||||||
use net_traits::response::HttpsState;
|
use net_traits::response::HttpsState;
|
||||||
|
use net_traits::response::{Response, ResponseBody};
|
||||||
use net_traits::storage_thread::StorageType;
|
use net_traits::storage_thread::StorageType;
|
||||||
use net_traits::{Metadata, NetworkError, ResourceThreads};
|
use net_traits::{Metadata, NetworkError, ResourceThreads};
|
||||||
use offscreen_gl_context::GLLimits;
|
use offscreen_gl_context::GLLimits;
|
||||||
|
@ -339,7 +341,10 @@ no_jsmanaged_fields!(SharedRt);
|
||||||
no_jsmanaged_fields!(TouchpadPressurePhase);
|
no_jsmanaged_fields!(TouchpadPressurePhase);
|
||||||
no_jsmanaged_fields!(USVString);
|
no_jsmanaged_fields!(USVString);
|
||||||
no_jsmanaged_fields!(ReferrerPolicy);
|
no_jsmanaged_fields!(ReferrerPolicy);
|
||||||
|
no_jsmanaged_fields!(Response);
|
||||||
|
no_jsmanaged_fields!(ResponseBody);
|
||||||
no_jsmanaged_fields!(ResourceThreads);
|
no_jsmanaged_fields!(ResourceThreads);
|
||||||
|
no_jsmanaged_fields!(StatusCode);
|
||||||
no_jsmanaged_fields!(SystemTime);
|
no_jsmanaged_fields!(SystemTime);
|
||||||
no_jsmanaged_fields!(RelativePos);
|
no_jsmanaged_fields!(RelativePos);
|
||||||
no_jsmanaged_fields!(OpaqueStyleAndLayoutData);
|
no_jsmanaged_fields!(OpaqueStyleAndLayoutData);
|
||||||
|
|
|
@ -209,7 +209,13 @@ impl Headers {
|
||||||
headers_for_request
|
headers_for_request
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_guard(&self, new_guard: Guard) {
|
pub fn for_response(global: GlobalRef) -> Root<Headers> {
|
||||||
|
let headers_for_response = Headers::new(global);
|
||||||
|
headers_for_response.guard.set(Guard::Response);
|
||||||
|
headers_for_response
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_guard(&self, new_guard: Guard) {
|
||||||
self.guard.set(new_guard)
|
self.guard.set(new_guard)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -346,7 +352,7 @@ pub fn is_forbidden_header_name(name: &str) -> bool {
|
||||||
// [3] https://tools.ietf.org/html/rfc7230#section-3.2.6
|
// [3] https://tools.ietf.org/html/rfc7230#section-3.2.6
|
||||||
// [4] https://www.rfc-editor.org/errata_search.php?rfc=7230
|
// [4] https://www.rfc-editor.org/errata_search.php?rfc=7230
|
||||||
fn validate_name_and_value(name: ByteString, value: ByteString)
|
fn validate_name_and_value(name: ByteString, value: ByteString)
|
||||||
-> Result<(String, Vec<u8>), Error> {
|
-> Fallible<(String, Vec<u8>)> {
|
||||||
let valid_name = try!(validate_name(name));
|
let valid_name = try!(validate_name(name));
|
||||||
if !is_field_content(&value) {
|
if !is_field_content(&value) {
|
||||||
return Err(Error::Type("Value is not valid".to_string()));
|
return Err(Error::Type("Value is not valid".to_string()));
|
||||||
|
@ -354,7 +360,7 @@ fn validate_name_and_value(name: ByteString, value: ByteString)
|
||||||
Ok((valid_name, value.into()))
|
Ok((valid_name, value.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate_name(name: ByteString) -> Result<String, Error> {
|
fn validate_name(name: ByteString) -> Fallible<String> {
|
||||||
if !is_field_name(&name) {
|
if !is_field_name(&name) {
|
||||||
return Err(Error::Type("Name is not valid".to_string()));
|
return Err(Error::Type("Name is not valid".to_string()));
|
||||||
}
|
}
|
||||||
|
@ -444,7 +450,7 @@ fn is_field_vchar(x: u8) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://tools.ietf.org/html/rfc5234#appendix-B.1
|
// https://tools.ietf.org/html/rfc5234#appendix-B.1
|
||||||
fn is_vchar(x: u8) -> bool {
|
pub fn is_vchar(x: u8) -> bool {
|
||||||
match x {
|
match x {
|
||||||
0x21...0x7E => true,
|
0x21...0x7E => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
|
@ -452,7 +458,7 @@ fn is_vchar(x: u8) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// http://tools.ietf.org/html/rfc7230#section-3.2.6
|
// http://tools.ietf.org/html/rfc7230#section-3.2.6
|
||||||
fn is_obs_text(x: u8) -> bool {
|
pub fn is_obs_text(x: u8) -> bool {
|
||||||
match x {
|
match x {
|
||||||
0x80...0xFF => true,
|
0x80...0xFF => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
|
|
|
@ -22,7 +22,6 @@ use dom::virtualmethods::VirtualMethods;
|
||||||
use encoding::EncodingRef;
|
use encoding::EncodingRef;
|
||||||
use encoding::all::UTF_8;
|
use encoding::all::UTF_8;
|
||||||
use hyper::header::ContentType;
|
use hyper::header::ContentType;
|
||||||
use hyper::http::RawStatus;
|
|
||||||
use hyper::mime::{Mime, TopLevel, SubLevel};
|
use hyper::mime::{Mime, TopLevel, SubLevel};
|
||||||
use hyper_serde::Serde;
|
use hyper_serde::Serde;
|
||||||
use ipc_channel::ipc;
|
use ipc_channel::ipc;
|
||||||
|
@ -335,7 +334,7 @@ impl AsyncResponseListener for StylesheetContext {
|
||||||
document.invalidate_stylesheets();
|
document.invalidate_stylesheets();
|
||||||
|
|
||||||
// FIXME: Revisit once consensus is reached at: https://github.com/whatwg/html/issues/1142
|
// FIXME: Revisit once consensus is reached at: https://github.com/whatwg/html/issues/1142
|
||||||
successful = metadata.status.map_or(false, |Serde(RawStatus(code, _))| code == 200);
|
successful = metadata.status.map_or(false, |(code, _)| code == 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
if elem.parser_inserted.get() {
|
if elem.parser_inserted.get() {
|
||||||
|
|
|
@ -24,7 +24,6 @@ use dom::htmlsourceelement::HTMLSourceElement;
|
||||||
use dom::mediaerror::MediaError;
|
use dom::mediaerror::MediaError;
|
||||||
use dom::node::{window_from_node, document_from_node, Node, UnbindContext};
|
use dom::node::{window_from_node, document_from_node, Node, UnbindContext};
|
||||||
use dom::virtualmethods::VirtualMethods;
|
use dom::virtualmethods::VirtualMethods;
|
||||||
use hyper_serde::Serde;
|
|
||||||
use ipc_channel::ipc;
|
use ipc_channel::ipc;
|
||||||
use ipc_channel::router::ROUTER;
|
use ipc_channel::router::ROUTER;
|
||||||
use net_traits::{AsyncResponseListener, AsyncResponseTarget, Metadata, NetworkError};
|
use net_traits::{AsyncResponseListener, AsyncResponseTarget, Metadata, NetworkError};
|
||||||
|
@ -66,7 +65,7 @@ impl AsyncResponseListener for HTMLMediaElementContext {
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|m| m.status
|
.and_then(|m| m.status
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|&Serde(ref s)| s.0 < 200 || s.0 >= 300))
|
.map(|&(s, _)| s < 200 || s >= 300))
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
if is_failure {
|
if is_failure {
|
||||||
// Ensure that the element doesn't receive any further notifications
|
// Ensure that the element doesn't receive any further notifications
|
||||||
|
|
|
@ -26,8 +26,6 @@ use dom::window::ScriptHelpers;
|
||||||
use encoding::label::encoding_from_whatwg_label;
|
use encoding::label::encoding_from_whatwg_label;
|
||||||
use encoding::types::{DecoderTrap, EncodingRef};
|
use encoding::types::{DecoderTrap, EncodingRef};
|
||||||
use html5ever::tree_builder::NextParserState;
|
use html5ever::tree_builder::NextParserState;
|
||||||
use hyper::http::RawStatus;
|
|
||||||
use hyper_serde::Serde;
|
|
||||||
use ipc_channel::ipc;
|
use ipc_channel::ipc;
|
||||||
use ipc_channel::router::ROUTER;
|
use ipc_channel::router::ROUTER;
|
||||||
use js::jsval::UndefinedValue;
|
use js::jsval::UndefinedValue;
|
||||||
|
@ -159,7 +157,7 @@ impl AsyncResponseListener for ScriptContext {
|
||||||
|
|
||||||
let status_code = self.metadata.as_ref().and_then(|m| {
|
let status_code = self.metadata.as_ref().and_then(|m| {
|
||||||
match m.status {
|
match m.status {
|
||||||
Some(Serde(RawStatus(c, _))) => Some(c),
|
Some((c, _)) => Some(c),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}).unwrap_or(0);
|
}).unwrap_or(0);
|
||||||
|
|
|
@ -372,6 +372,7 @@ pub mod progressevent;
|
||||||
pub mod radionodelist;
|
pub mod radionodelist;
|
||||||
pub mod range;
|
pub mod range;
|
||||||
pub mod request;
|
pub mod request;
|
||||||
|
pub mod response;
|
||||||
pub mod screen;
|
pub mod screen;
|
||||||
pub mod serviceworker;
|
pub mod serviceworker;
|
||||||
pub mod serviceworkercontainer;
|
pub mod serviceworkercontainer;
|
||||||
|
|
290
components/script/dom/response.rs
Normal file
290
components/script/dom/response.rs
Normal file
|
@ -0,0 +1,290 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* 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 core::cell::Cell;
|
||||||
|
use dom::bindings::cell::DOMRefCell;
|
||||||
|
use dom::bindings::codegen::Bindings::HeadersBinding::HeadersMethods;
|
||||||
|
use dom::bindings::codegen::Bindings::ResponseBinding;
|
||||||
|
use dom::bindings::codegen::Bindings::ResponseBinding::{ResponseMethods, ResponseType as DOMResponseType};
|
||||||
|
use dom::bindings::error::{Error, Fallible};
|
||||||
|
use dom::bindings::global::GlobalRef;
|
||||||
|
use dom::bindings::js::{JS, MutNullableHeap, Root};
|
||||||
|
use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object};
|
||||||
|
use dom::bindings::str::{ByteString, USVString};
|
||||||
|
use dom::headers::{Headers, Guard};
|
||||||
|
use dom::headers::{is_vchar, is_obs_text};
|
||||||
|
use hyper::status::StatusCode;
|
||||||
|
use net_traits::response::{ResponseBody as NetTraitsResponseBody};
|
||||||
|
use std::str::FromStr;
|
||||||
|
use url::Position;
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
|
#[dom_struct]
|
||||||
|
pub struct Response {
|
||||||
|
reflector_: Reflector,
|
||||||
|
headers_reflector: MutNullableHeap<JS<Headers>>,
|
||||||
|
mime_type: DOMRefCell<Vec<u8>>,
|
||||||
|
body_used: Cell<bool>,
|
||||||
|
/// `None` can be considered a StatusCode of `0`.
|
||||||
|
#[ignore_heap_size_of = "Defined in hyper"]
|
||||||
|
status: DOMRefCell<Option<StatusCode>>,
|
||||||
|
raw_status: DOMRefCell<Option<(u16, Vec<u8>)>>,
|
||||||
|
response_type: DOMRefCell<DOMResponseType>,
|
||||||
|
url: DOMRefCell<Option<Url>>,
|
||||||
|
url_list: DOMRefCell<Vec<Url>>,
|
||||||
|
// For now use the existing NetTraitsResponseBody enum, until body
|
||||||
|
// is implemented.
|
||||||
|
body: DOMRefCell<NetTraitsResponseBody>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Response {
|
||||||
|
pub fn new_inherited() -> Response {
|
||||||
|
Response {
|
||||||
|
reflector_: Reflector::new(),
|
||||||
|
headers_reflector: Default::default(),
|
||||||
|
mime_type: DOMRefCell::new("".to_string().into_bytes()),
|
||||||
|
body_used: Cell::new(false),
|
||||||
|
status: DOMRefCell::new(Some(StatusCode::Ok)),
|
||||||
|
raw_status: DOMRefCell::new(Some((200, b"OK".to_vec()))),
|
||||||
|
response_type: DOMRefCell::new(DOMResponseType::Default),
|
||||||
|
url: DOMRefCell::new(None),
|
||||||
|
url_list: DOMRefCell::new(vec![]),
|
||||||
|
body: DOMRefCell::new(NetTraitsResponseBody::Empty),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://fetch.spec.whatwg.org/#dom-response
|
||||||
|
pub fn new(global: GlobalRef) -> Root<Response> {
|
||||||
|
reflect_dom_object(box Response::new_inherited(), global, ResponseBinding::Wrap)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn Constructor(global: GlobalRef, _body: Option<USVString>, init: &ResponseBinding::ResponseInit)
|
||||||
|
-> Fallible<Root<Response>> {
|
||||||
|
// Step 1
|
||||||
|
if init.status < 200 || init.status > 599 {
|
||||||
|
return Err(Error::Range(
|
||||||
|
format!("init's status member should be in the range 200 to 599, inclusive, but is {}"
|
||||||
|
, init.status)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 2
|
||||||
|
if !is_valid_status_text(&init.statusText) {
|
||||||
|
return Err(Error::Type("init's statusText member does not match the reason-phrase token production"
|
||||||
|
.to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 3
|
||||||
|
let r = Response::new(global);
|
||||||
|
|
||||||
|
// Step 4
|
||||||
|
*r.status.borrow_mut() = Some(StatusCode::from_u16(init.status));
|
||||||
|
|
||||||
|
// Step 5
|
||||||
|
*r.raw_status.borrow_mut() = Some((init.status, init.statusText.clone().into()));
|
||||||
|
|
||||||
|
// Step 6
|
||||||
|
if let Some(ref headers_member) = init.headers {
|
||||||
|
// Step 6.1
|
||||||
|
// TODO: Figure out how/if we should make r's response's
|
||||||
|
// header list and r's Headers object the same thing. For
|
||||||
|
// now just working with r's Headers object. Also, the
|
||||||
|
// header list should already be empty so this step may be
|
||||||
|
// unnecessary.
|
||||||
|
r.Headers().empty_header_list();
|
||||||
|
|
||||||
|
// Step 6.2
|
||||||
|
try!(r.Headers().fill(Some(headers_member.clone())));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 7
|
||||||
|
if let Some(_) = _body {
|
||||||
|
// Step 7.1
|
||||||
|
if is_null_body_status(init.status) {
|
||||||
|
return Err(Error::Type(
|
||||||
|
"Body is non-null but init's status member is a null body status".to_string()));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Step 7.2
|
||||||
|
let content_type: Option<ByteString> = None;
|
||||||
|
|
||||||
|
// Step 7.3
|
||||||
|
// TODO: Extract body and implement step 7.3.
|
||||||
|
|
||||||
|
// Step 7.4
|
||||||
|
if let Some(content_type_contents) = content_type {
|
||||||
|
if !r.Headers().Has(ByteString::new(b"Content-Type".to_vec())).unwrap() {
|
||||||
|
try!(r.Headers().Append(ByteString::new(b"Content-Type".to_vec()), content_type_contents));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 8
|
||||||
|
*r.mime_type.borrow_mut() = r.Headers().extract_mime_type();
|
||||||
|
|
||||||
|
// Step 9
|
||||||
|
// TODO: `entry settings object` is not implemented in Servo yet.
|
||||||
|
|
||||||
|
// Step 10
|
||||||
|
// TODO: Write this step once Promises are merged in
|
||||||
|
|
||||||
|
// Step 11
|
||||||
|
Ok(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://fetch.spec.whatwg.org/#dom-response-error
|
||||||
|
pub fn Error(global: GlobalRef) -> Root<Response> {
|
||||||
|
let r = Response::new(global);
|
||||||
|
*r.response_type.borrow_mut() = DOMResponseType::Error;
|
||||||
|
r.Headers().set_guard(Guard::Immutable);
|
||||||
|
*r.raw_status.borrow_mut() = Some((0, b"".to_vec()));
|
||||||
|
r
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://fetch.spec.whatwg.org/#dom-response-redirect
|
||||||
|
pub fn Redirect(global: GlobalRef, url: USVString, status: u16) -> Fallible<Root<Response>> {
|
||||||
|
// Step 1
|
||||||
|
// TODO: `entry settings object` is not implemented in Servo yet.
|
||||||
|
let base_url = global.get_url();
|
||||||
|
let parsed_url = base_url.join(&url.0);
|
||||||
|
|
||||||
|
// Step 2
|
||||||
|
let url = match parsed_url {
|
||||||
|
Ok(url) => url,
|
||||||
|
Err(_) => return Err(Error::Type("Url could not be parsed".to_string())),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Step 3
|
||||||
|
if !is_redirect_status(status) {
|
||||||
|
return Err(Error::Range("status is not a redirect status".to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 4
|
||||||
|
// see Step 4 continued
|
||||||
|
let r = Response::new(global);
|
||||||
|
|
||||||
|
// Step 5
|
||||||
|
*r.status.borrow_mut() = Some(StatusCode::from_u16(status));
|
||||||
|
*r.raw_status.borrow_mut() = Some((status, b"".to_vec()));
|
||||||
|
|
||||||
|
// Step 6
|
||||||
|
let url_bytestring = ByteString::from_str(url.as_str()).unwrap_or(ByteString::new(b"".to_vec()));
|
||||||
|
try!(r.Headers().Set(ByteString::new(b"Location".to_vec()), url_bytestring));
|
||||||
|
|
||||||
|
// Step 4 continued
|
||||||
|
// Headers Guard is set to Immutable here to prevent error in Step 6
|
||||||
|
r.Headers().set_guard(Guard::Immutable);
|
||||||
|
|
||||||
|
// Step 7
|
||||||
|
Ok(r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://fetch.spec.whatwg.org/#redirect-status
|
||||||
|
fn is_redirect_status(status: u16) -> bool {
|
||||||
|
status == 301 || status == 302 || status == 303 || status == 307 || status == 308
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://tools.ietf.org/html/rfc7230#section-3.1.2
|
||||||
|
fn is_valid_status_text(status_text: &ByteString) -> bool {
|
||||||
|
// reason-phrase = *( HTAB / SP / VCHAR / obs-text )
|
||||||
|
for byte in status_text.iter() {
|
||||||
|
if !(*byte == b'\t' || *byte == b' ' || is_vchar(*byte) || is_obs_text(*byte)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://fetch.spec.whatwg.org/#null-body-status
|
||||||
|
fn is_null_body_status(status: u16) -> bool {
|
||||||
|
status == 101 || status == 204 || status == 205 || status == 304
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ResponseMethods for Response {
|
||||||
|
// https://fetch.spec.whatwg.org/#dom-response-type
|
||||||
|
fn Type(&self) -> DOMResponseType {
|
||||||
|
*self.response_type.borrow()//into()
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://fetch.spec.whatwg.org/#dom-response-url
|
||||||
|
fn Url(&self) -> USVString {
|
||||||
|
USVString(String::from((*self.url.borrow()).as_ref().map(|u| serialize_without_fragment(u)).unwrap_or("")))
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://fetch.spec.whatwg.org/#dom-response-redirected
|
||||||
|
fn Redirected(&self) -> bool {
|
||||||
|
let url_list_len = self.url_list.borrow().len();
|
||||||
|
url_list_len > 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://fetch.spec.whatwg.org/#dom-response-status
|
||||||
|
fn Status(&self) -> u16 {
|
||||||
|
match *self.raw_status.borrow() {
|
||||||
|
Some((s, _)) => s,
|
||||||
|
None => 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://fetch.spec.whatwg.org/#dom-response-ok
|
||||||
|
fn Ok(&self) -> bool {
|
||||||
|
match *self.status.borrow() {
|
||||||
|
Some(s) => {
|
||||||
|
let status_num = s.to_u16();
|
||||||
|
return status_num >= 200 && status_num <= 299;
|
||||||
|
}
|
||||||
|
None => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://fetch.spec.whatwg.org/#dom-response-statustext
|
||||||
|
fn StatusText(&self) -> ByteString {
|
||||||
|
match *self.raw_status.borrow() {
|
||||||
|
Some((_, ref st)) => ByteString::new(st.clone()),
|
||||||
|
None => ByteString::new(b"OK".to_vec()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://fetch.spec.whatwg.org/#dom-response-headers
|
||||||
|
fn Headers(&self) -> Root<Headers> {
|
||||||
|
self.headers_reflector.or_init(|| Headers::for_response(self.global().r()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://fetch.spec.whatwg.org/#dom-response-clone
|
||||||
|
fn Clone(&self) -> Fallible<Root<Response>> {
|
||||||
|
// Step 1
|
||||||
|
// TODO: This step relies on body and stream, which are still unimplemented.
|
||||||
|
|
||||||
|
// Step 2
|
||||||
|
let new_response = Response::new(self.global().r());
|
||||||
|
new_response.Headers().set_guard(self.Headers().get_guard());
|
||||||
|
|
||||||
|
// https://fetch.spec.whatwg.org/#concept-response-clone
|
||||||
|
// Instead of storing a net_traits::Response internally, we
|
||||||
|
// only store the relevant fields, and only clone them here
|
||||||
|
*new_response.response_type.borrow_mut() = self.response_type.borrow().clone();
|
||||||
|
*new_response.status.borrow_mut() = self.status.borrow().clone();
|
||||||
|
*new_response.raw_status.borrow_mut() = self.raw_status.borrow().clone();
|
||||||
|
*new_response.url.borrow_mut() = self.url.borrow().clone();
|
||||||
|
*new_response.url_list.borrow_mut() = self.url_list.borrow().clone();
|
||||||
|
|
||||||
|
if *self.body.borrow() != NetTraitsResponseBody::Empty {
|
||||||
|
*new_response.body.borrow_mut() = self.body.borrow().clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 3
|
||||||
|
// TODO: This step relies on promises, which are still unimplemented.
|
||||||
|
|
||||||
|
// Step 4
|
||||||
|
Ok(new_response)
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://fetch.spec.whatwg.org/#dom-body-bodyused
|
||||||
|
fn BodyUsed(&self) -> bool {
|
||||||
|
self.body_used.get()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_without_fragment(url: &Url) -> &str {
|
||||||
|
&url[..Position::AfterQuery]
|
||||||
|
}
|
37
components/script/dom/webidls/Response.webidl
Normal file
37
components/script/dom/webidls/Response.webidl
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* 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/. */
|
||||||
|
|
||||||
|
// https://fetch.spec.whatwg.org/#response-class
|
||||||
|
|
||||||
|
// TODO: pass 'optional ResponseBodyInit? body = null' to constructor in place of USVString
|
||||||
|
[Constructor(optional USVString? body = null, optional ResponseInit init),
|
||||||
|
Exposed=(Window,Worker)]
|
||||||
|
interface Response {
|
||||||
|
[NewObject] static Response error();
|
||||||
|
[NewObject, Throws] static Response redirect(USVString url, optional unsigned short status = 302);
|
||||||
|
|
||||||
|
readonly attribute ResponseType type;
|
||||||
|
|
||||||
|
readonly attribute USVString url;
|
||||||
|
readonly attribute boolean redirected;
|
||||||
|
readonly attribute unsigned short status;
|
||||||
|
readonly attribute boolean ok;
|
||||||
|
readonly attribute ByteString statusText;
|
||||||
|
[SameObject] readonly attribute Headers headers;
|
||||||
|
// readonly attribute ReadableStream? body;
|
||||||
|
// [SameObject] readonly attribute Promise<Headers> trailer;
|
||||||
|
|
||||||
|
[NewObject, Throws] Response clone();
|
||||||
|
};
|
||||||
|
Response implements Body;
|
||||||
|
|
||||||
|
dictionary ResponseInit {
|
||||||
|
unsigned short status = 200;
|
||||||
|
ByteString statusText = "OK";
|
||||||
|
HeadersInit headers;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ResponseType { "basic", "cors", "default", "error", "opaque", "opaqueredirect" };
|
||||||
|
|
||||||
|
// typedef (BodyInit or ReadableStream) ResponseBodyInit;
|
|
@ -36,7 +36,6 @@ use encoding::types::{DecoderTrap, EncoderTrap, Encoding, EncodingRef};
|
||||||
use euclid::length::Length;
|
use euclid::length::Length;
|
||||||
use hyper::header::Headers;
|
use hyper::header::Headers;
|
||||||
use hyper::header::{ContentLength, ContentType};
|
use hyper::header::{ContentLength, ContentType};
|
||||||
use hyper::http::RawStatus;
|
|
||||||
use hyper::method::Method;
|
use hyper::method::Method;
|
||||||
use hyper::mime::{self, Mime, Attr as MimeAttr, Value as MimeValue};
|
use hyper::mime::{self, Mime, Attr as MimeAttr, Value as MimeValue};
|
||||||
use hyper_serde::Serde;
|
use hyper_serde::Serde;
|
||||||
|
@ -91,7 +90,7 @@ struct XHRContext {
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum XHRProgress {
|
pub enum XHRProgress {
|
||||||
/// Notify that headers have been received
|
/// Notify that headers have been received
|
||||||
HeadersReceived(GenerationId, Option<Headers>, Option<RawStatus>),
|
HeadersReceived(GenerationId, Option<Headers>, Option<(u16, Vec<u8>)>),
|
||||||
/// Partial progress (after receiving headers), containing portion of the response
|
/// Partial progress (after receiving headers), containing portion of the response
|
||||||
Loading(GenerationId, ByteString),
|
Loading(GenerationId, ByteString),
|
||||||
/// Loading is done
|
/// Loading is done
|
||||||
|
@ -879,7 +878,7 @@ impl XMLHttpRequest {
|
||||||
self.process_partial_response(XHRProgress::HeadersReceived(
|
self.process_partial_response(XHRProgress::HeadersReceived(
|
||||||
gen_id,
|
gen_id,
|
||||||
metadata.headers.map(Serde::into_inner),
|
metadata.headers.map(Serde::into_inner),
|
||||||
metadata.status.map(Serde::into_inner)));
|
metadata.status));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -943,9 +942,9 @@ impl XMLHttpRequest {
|
||||||
// Part of step 13, send() (processing response)
|
// Part of step 13, send() (processing response)
|
||||||
// XXXManishearth handle errors, if any (substep 1)
|
// XXXManishearth handle errors, if any (substep 1)
|
||||||
// Substep 2
|
// Substep 2
|
||||||
status.map(|RawStatus(code, reason)| {
|
status.map(|(code, reason)| {
|
||||||
self.status.set(code);
|
self.status.set(code);
|
||||||
*self.status_text.borrow_mut() = ByteString::new(reason.into_owned().into_bytes());
|
*self.status_text.borrow_mut() = ByteString::new(reason);
|
||||||
});
|
});
|
||||||
headers.as_ref().map(|h| *self.response_headers.borrow_mut() = h.clone());
|
headers.as_ref().map(|h| *self.response_headers.borrow_mut() = h.clone());
|
||||||
|
|
||||||
|
|
1
components/servo/Cargo.lock
generated
1
components/servo/Cargo.lock
generated
|
@ -487,6 +487,7 @@ name = "devtools"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"devtools_traits 0.0.1",
|
"devtools_traits 0.0.1",
|
||||||
|
"encoding 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"hyper 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
"hyper 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"hyper_serde 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"hyper_serde 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ipc-channel 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ipc-channel 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
|
1
ports/cef/Cargo.lock
generated
1
ports/cef/Cargo.lock
generated
|
@ -445,6 +445,7 @@ name = "devtools"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"devtools_traits 0.0.1",
|
"devtools_traits 0.0.1",
|
||||||
|
"encoding 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"hyper 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
"hyper 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"hyper_serde 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"hyper_serde 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ipc-channel 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ipc-channel 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
|
|
@ -13,7 +13,6 @@ use hyper::header::{AccessControlRequestHeaders, AccessControlRequestMethod, Use
|
||||||
use hyper::header::{CacheControl, ContentLanguage, ContentLength, ContentType, Expires, LastModified};
|
use hyper::header::{CacheControl, ContentLanguage, ContentLength, ContentType, Expires, LastModified};
|
||||||
use hyper::header::{Headers, HttpDate, Host, Referer as HyperReferer};
|
use hyper::header::{Headers, HttpDate, Host, Referer as HyperReferer};
|
||||||
use hyper::header::{Location, SetCookie, Pragma, Encoding, qitem};
|
use hyper::header::{Location, SetCookie, Pragma, Encoding, qitem};
|
||||||
use hyper::http::RawStatus;
|
|
||||||
use hyper::method::Method;
|
use hyper::method::Method;
|
||||||
use hyper::mime::{Mime, TopLevel, SubLevel};
|
use hyper::mime::{Mime, TopLevel, SubLevel};
|
||||||
use hyper::server::{Handler, Listening, Server};
|
use hyper::server::{Handler, Listening, Server};
|
||||||
|
@ -27,7 +26,6 @@ use net::http_loader::HttpState;
|
||||||
use net_traits::FetchTaskTarget;
|
use net_traits::FetchTaskTarget;
|
||||||
use net_traits::request::{Origin, RedirectMode, Referer, Request, RequestMode};
|
use net_traits::request::{Origin, RedirectMode, Referer, Request, RequestMode};
|
||||||
use net_traits::response::{CacheState, Response, ResponseBody, ResponseType};
|
use net_traits::response::{CacheState, Response, ResponseBody, ResponseType};
|
||||||
use std::borrow::Cow;
|
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
@ -834,7 +832,7 @@ fn test_fetch_with_devtools() {
|
||||||
|
|
||||||
let httpresponse = DevtoolsHttpResponse {
|
let httpresponse = DevtoolsHttpResponse {
|
||||||
headers: Some(response_headers),
|
headers: Some(response_headers),
|
||||||
status: Some(RawStatus(200, Cow::Borrowed("OK"))),
|
status: Some((200, b"OK".to_vec())),
|
||||||
body: None,
|
body: None,
|
||||||
pipeline_id: pipeline_id,
|
pipeline_id: pipeline_id,
|
||||||
};
|
};
|
||||||
|
|
|
@ -18,7 +18,6 @@ use hyper::http::RawStatus;
|
||||||
use hyper::method::Method;
|
use hyper::method::Method;
|
||||||
use hyper::mime::{Mime, SubLevel, TopLevel};
|
use hyper::mime::{Mime, SubLevel, TopLevel};
|
||||||
use hyper::status::StatusCode;
|
use hyper::status::StatusCode;
|
||||||
use hyper_serde::Serde;
|
|
||||||
use msg::constellation_msg::{PipelineId, ReferrerPolicy};
|
use msg::constellation_msg::{PipelineId, ReferrerPolicy};
|
||||||
use net::cookie::Cookie;
|
use net::cookie::Cookie;
|
||||||
use net::cookie_storage::CookieStorage;
|
use net::cookie_storage::CookieStorage;
|
||||||
|
@ -80,7 +79,7 @@ fn respond_with_headers(body: Vec<u8>, mut headers: Headers) -> MockResponse {
|
||||||
MockResponse::new(
|
MockResponse::new(
|
||||||
headers,
|
headers,
|
||||||
StatusCode::Ok,
|
StatusCode::Ok,
|
||||||
RawStatus(200, Cow::Borrowed("Ok")),
|
RawStatus(200, Cow::Borrowed("OK")),
|
||||||
body
|
body
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -537,7 +536,7 @@ fn test_request_and_response_data_with_network_messages() {
|
||||||
|
|
||||||
let httpresponse = DevtoolsHttpResponse {
|
let httpresponse = DevtoolsHttpResponse {
|
||||||
headers: Some(response_headers),
|
headers: Some(response_headers),
|
||||||
status: Some(RawStatus(200, Cow::Borrowed("Ok"))),
|
status: Some((200, b"OK".to_vec())),
|
||||||
body: None,
|
body: None,
|
||||||
pipeline_id: pipeline_id,
|
pipeline_id: pipeline_id,
|
||||||
};
|
};
|
||||||
|
@ -623,7 +622,7 @@ fn test_redirected_request_to_devtools() {
|
||||||
|
|
||||||
assert!(devhttprequest.method == Method::Post);
|
assert!(devhttprequest.method == Method::Post);
|
||||||
assert!(devhttprequest.url == url);
|
assert!(devhttprequest.url == url);
|
||||||
assert!(devhttpresponse.status == Some(RawStatus(301, Cow::Borrowed("Moved Permanently"))));
|
assert!(devhttpresponse.status == Some((301, "Moved Permanently".as_bytes().to_vec())));
|
||||||
|
|
||||||
let devhttprequest = expect_devtools_http_request(&devtools_port);
|
let devhttprequest = expect_devtools_http_request(&devtools_port);
|
||||||
let devhttpresponse = expect_devtools_http_response(&devtools_port);
|
let devhttpresponse = expect_devtools_http_response(&devtools_port);
|
||||||
|
@ -631,7 +630,7 @@ fn test_redirected_request_to_devtools() {
|
||||||
|
|
||||||
assert!(devhttprequest.method == Method::Get);
|
assert!(devhttprequest.method == Method::Get);
|
||||||
assert!(devhttprequest.url == url);
|
assert!(devhttprequest.url == url);
|
||||||
assert!(devhttpresponse.status == Some(RawStatus(200, Cow::Borrowed("Ok"))));
|
assert!(devhttpresponse.status == Some((200, b"OK".to_vec())));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1586,7 +1585,7 @@ fn test_auth_ui_sets_header_on_401() {
|
||||||
Err(e) => panic!("response contained error {:?}", e),
|
Err(e) => panic!("response contained error {:?}", e),
|
||||||
Ok(response) => {
|
Ok(response) => {
|
||||||
assert_eq!(response.metadata.status,
|
assert_eq!(response.metadata.status,
|
||||||
Some(Serde(RawStatus(200, Cow::Borrowed("Ok")))));
|
Some((200, b"OK".to_vec())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1621,7 +1620,7 @@ fn test_auth_ui_needs_www_auth() {
|
||||||
Err(e) => panic!("response contained error {:?}", e),
|
Err(e) => panic!("response contained error {:?}", e),
|
||||||
Ok(response) => {
|
Ok(response) => {
|
||||||
assert_eq!(response.metadata.status,
|
assert_eq!(response.metadata.status,
|
||||||
Some(Serde(RawStatus(401, Cow::Borrowed("Unauthorized")))));
|
Some((401, "Unauthorized".as_bytes().to_vec())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1947,7 +1946,7 @@ fn load_request_for_custom_response(expected_body: Vec<u8>) -> (Metadata, String
|
||||||
fn test_custom_response() {
|
fn test_custom_response() {
|
||||||
let expected_body = b"Yay!".to_vec();
|
let expected_body = b"Yay!".to_vec();
|
||||||
let (metadata, body) = load_request_for_custom_response(expected_body.clone());
|
let (metadata, body) = load_request_for_custom_response(expected_body.clone());
|
||||||
assert_eq!(metadata.status, Some(Serde(RawStatus(200, Cow::Borrowed("OK")))));
|
assert_eq!(metadata.status, Some((200, b"OK".to_vec())));
|
||||||
assert_eq!(body, String::from_utf8(expected_body).unwrap());
|
assert_eq!(body, String::from_utf8(expected_body).unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
[response-error.html]
|
|
||||||
type: testharness
|
|
||||||
[Throws RangeError when responseInit's status is 0]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Throws RangeError when responseInit's status is 100]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Throws RangeError when responseInit's status is 199]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Throws RangeError when responseInit's status is 600]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Throws RangeError when responseInit's status is 1000]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Throws TypeError when responseInit's statusText is \n]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Throws TypeError when responseInit's statusText is Ā]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Throws TypeError when building a response with body and a body status of 204]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Throws TypeError when building a response with body and a body status of 205]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Throws TypeError when building a response with body and a body status of 304]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
[response-init-001.html]
|
[response-init-001.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
expected: ERROR
|
[Check default value for body attribute]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
[response-static-redirect.html]
|
|
||||||
type: testharness
|
|
||||||
[Check default redirect response]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Check response returned by static method redirect(), status = 301]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Check response returned by static method redirect(), status = 302]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Check response returned by static method redirect(), status = 303]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Check response returned by static method redirect(), status = 307]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Check response returned by static method redirect(), status = 308]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Check error returned when giving invalid url to redirect()]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Check error returned when giving invalid status to redirect(), status = 200]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Check error returned when giving invalid status to redirect(), status = 309]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Check error returned when giving invalid status to redirect(), status = 400]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Check error returned when giving invalid status to redirect(), status = 500]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -148,6 +148,7 @@ test_interfaces([
|
||||||
"RadioNodeList",
|
"RadioNodeList",
|
||||||
"Range",
|
"Range",
|
||||||
"Request",
|
"Request",
|
||||||
|
"Response",
|
||||||
"Screen",
|
"Screen",
|
||||||
"Storage",
|
"Storage",
|
||||||
"StorageEvent",
|
"StorageEvent",
|
||||||
|
|
|
@ -90,6 +90,7 @@ test_interfaces([
|
||||||
"RadioNodeList",
|
"RadioNodeList",
|
||||||
"Range",
|
"Range",
|
||||||
"Request",
|
"Request",
|
||||||
|
"Response",
|
||||||
"Screen",
|
"Screen",
|
||||||
"Storage",
|
"Storage",
|
||||||
"StorageEvent",
|
"StorageEvent",
|
||||||
|
|
|
@ -60,4 +60,4 @@
|
||||||
}, "Check " + attributeName + " init values and associated getter");
|
}, "Check " + attributeName + " init values and associated getter");
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
var url = "http://test.url:1234/";
|
var url = "http://test.url:1234/";
|
||||||
test(function() {
|
test(function() {
|
||||||
redirectResponse = Response.redirect(url);
|
redirectResponse = Response.redirect(url);
|
||||||
assert_equals(redirectResponse.status, 302, "Default redictect status is 302");
|
assert_equals(redirectResponse.status, 302, "Default redirect status is 302");
|
||||||
assert_equals(redirectResponse.headers.get("Location"), url,
|
assert_equals(redirectResponse.headers.get("Location"), url,
|
||||||
"redirected response has Location header with the correct url");
|
"redirected response has Location header with the correct url");
|
||||||
}, "Check default redirect response");
|
}, "Check default redirect response");
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
redirectStatus.forEach(function(status) {
|
redirectStatus.forEach(function(status) {
|
||||||
test(function() {
|
test(function() {
|
||||||
redirectResponse = Response.redirect(url, status);
|
redirectResponse = Response.redirect(url, status);
|
||||||
assert_equals(redirectResponse.status, status, "Redictect status is " + status);
|
assert_equals(redirectResponse.status, status, "Redirect status is " + status);
|
||||||
}, "Check response returned by static method redirect(), status = " + status);
|
}, "Check response returned by static method redirect(), status = " + status);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue