mirror of
https://github.com/servo/servo.git
synced 2025-08-06 06:00:15 +01:00
net: Make most of the resource task messages serializable.
This commit is contained in:
parent
7e77285745
commit
9c9d7dc93b
15 changed files with 373 additions and 105 deletions
|
@ -10,8 +10,6 @@
|
|||
#![feature(vec_push_all)]
|
||||
#![plugin(serde_macros)]
|
||||
|
||||
#![plugin(serde_macros)]
|
||||
|
||||
extern crate euclid;
|
||||
extern crate hyper;
|
||||
extern crate ipc_channel;
|
||||
|
@ -24,13 +22,19 @@ extern crate url;
|
|||
extern crate util;
|
||||
extern crate msg;
|
||||
|
||||
use hyper::header::{ContentType, Headers};
|
||||
use hyper::header::{ContentType, Header, Headers, HeadersItems};
|
||||
use hyper::http::RawStatus;
|
||||
use hyper::method::Method;
|
||||
use hyper::mime::{Mime, Attr};
|
||||
use msg::constellation_msg::{PipelineId};
|
||||
use serde::de;
|
||||
use serde::ser;
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
use url::Url;
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::str::FromStr;
|
||||
use std::sync::mpsc::{channel, Receiver, Sender};
|
||||
use std::thread;
|
||||
|
||||
|
@ -46,14 +50,14 @@ pub mod image {
|
|||
pub mod base;
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Deserialize, Serialize)]
|
||||
pub struct LoadData {
|
||||
pub url: Url,
|
||||
pub method: Method,
|
||||
pub url: SerializableUrl,
|
||||
pub method: SerializableMethod,
|
||||
/// Headers that will apply to the initial request only
|
||||
pub headers: Headers,
|
||||
pub headers: SerializableHeaders,
|
||||
/// Headers that will apply to the initial request and any redirects
|
||||
pub preserved_headers: Headers,
|
||||
pub preserved_headers: SerializableHeaders,
|
||||
pub data: Option<Vec<u8>>,
|
||||
pub cors: Option<ResourceCORSData>,
|
||||
pub pipeline_id: Option<PipelineId>,
|
||||
|
@ -62,10 +66,10 @@ pub struct LoadData {
|
|||
impl LoadData {
|
||||
pub fn new(url: Url, id: Option<PipelineId>) -> LoadData {
|
||||
LoadData {
|
||||
url: url,
|
||||
method: Method::Get,
|
||||
headers: Headers::new(),
|
||||
preserved_headers: Headers::new(),
|
||||
url: SerializableUrl(url),
|
||||
method: SerializableMethod(Method::Get),
|
||||
headers: SerializableHeaders(Headers::new()),
|
||||
preserved_headers: SerializableHeaders(Headers::new()),
|
||||
data: None,
|
||||
cors: None,
|
||||
pipeline_id: id,
|
||||
|
@ -87,13 +91,14 @@ pub trait AsyncResponseListener {
|
|||
|
||||
/// Data for passing between threads/processes to indicate a particular action to
|
||||
/// take on a provided network listener.
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub enum ResponseAction {
|
||||
/// Invoke headers_available
|
||||
HeadersAvailable(Metadata),
|
||||
/// Invoke data_available
|
||||
DataAvailable(Vec<u8>),
|
||||
/// Invoke response_complete
|
||||
ResponseComplete(Result<(), String>)
|
||||
ResponseComplete(SerializableStringResult)
|
||||
}
|
||||
|
||||
impl ResponseAction {
|
||||
|
@ -102,7 +107,7 @@ impl ResponseAction {
|
|||
match self {
|
||||
ResponseAction::HeadersAvailable(m) => listener.headers_available(m),
|
||||
ResponseAction::DataAvailable(d) => listener.data_available(d),
|
||||
ResponseAction::ResponseComplete(r) => listener.response_complete(r),
|
||||
ResponseAction::ResponseComplete(r) => listener.response_complete(r.0),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -132,9 +137,9 @@ pub enum ControlMsg {
|
|||
/// Request the data associated with a particular URL
|
||||
Load(LoadData, LoadConsumer),
|
||||
/// Store a set of cookies for a given originating URL
|
||||
SetCookiesForUrl(Url, String, CookieSource),
|
||||
SetCookiesForUrl(SerializableUrl, String, CookieSource),
|
||||
/// Retrieve the stored cookies for a given URL
|
||||
GetCookiesForUrl(Url, Sender<Option<String>>, CookieSource),
|
||||
GetCookiesForUrl(SerializableUrl, Sender<Option<String>>, CookieSource),
|
||||
/// Store a domain's STS information
|
||||
SetHSTSEntryForHost(String, IncludeSubdomains, Option<u64>),
|
||||
Exit
|
||||
|
@ -210,43 +215,43 @@ pub struct LoadResponse {
|
|||
pub progress_port: Receiver<ProgressMsg>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Deserialize, Serialize)]
|
||||
pub struct ResourceCORSData {
|
||||
/// CORS Preflight flag
|
||||
pub preflight: bool,
|
||||
/// Origin of CORS Request
|
||||
pub origin: Url
|
||||
pub origin: SerializableUrl,
|
||||
}
|
||||
|
||||
/// Metadata about a loaded resource, such as is obtained from HTTP headers.
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Deserialize, Serialize)]
|
||||
pub struct Metadata {
|
||||
/// Final URL after redirects.
|
||||
pub final_url: Url,
|
||||
pub final_url: SerializableUrl,
|
||||
|
||||
/// MIME type / subtype.
|
||||
pub content_type: Option<(ContentType)>,
|
||||
pub content_type: Option<(SerializableContentType)>,
|
||||
|
||||
/// Character set.
|
||||
pub charset: Option<String>,
|
||||
|
||||
/// Headers
|
||||
pub headers: Option<Headers>,
|
||||
pub headers: Option<SerializableHeaders>,
|
||||
|
||||
/// HTTP Status
|
||||
pub status: Option<RawStatus>,
|
||||
pub status: Option<SerializableRawStatus>,
|
||||
}
|
||||
|
||||
impl Metadata {
|
||||
/// Metadata with defaults for everything optional.
|
||||
pub fn default(url: Url) -> Self {
|
||||
Metadata {
|
||||
final_url: url,
|
||||
final_url: SerializableUrl(url),
|
||||
content_type: None,
|
||||
charset: None,
|
||||
headers: None,
|
||||
// https://fetch.spec.whatwg.org/#concept-response-status-message
|
||||
status: Some(RawStatus(200, "OK".into())),
|
||||
status: Some(SerializableRawStatus(RawStatus(200, "OK".into()))),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -255,7 +260,7 @@ impl Metadata {
|
|||
match content_type {
|
||||
None => (),
|
||||
Some(mime) => {
|
||||
self.content_type = Some(ContentType(mime.clone()));
|
||||
self.content_type = Some(SerializableContentType(ContentType(mime.clone())));
|
||||
let &Mime(_, _, ref parameters) = mime;
|
||||
for &(ref k, ref v) in parameters.iter() {
|
||||
if &Attr::Charset == k {
|
||||
|
@ -268,7 +273,7 @@ impl Metadata {
|
|||
}
|
||||
|
||||
/// The creator of a given cookie
|
||||
#[derive(PartialEq, Copy, Clone)]
|
||||
#[derive(PartialEq, Copy, Clone, Deserialize, Serialize)]
|
||||
pub enum CookieSource {
|
||||
/// An HTTP API
|
||||
HTTP,
|
||||
|
@ -277,12 +282,12 @@ pub enum CookieSource {
|
|||
}
|
||||
|
||||
/// Messages sent in response to a `Load` message
|
||||
#[derive(PartialEq,Debug)]
|
||||
#[derive(PartialEq, Debug, Deserialize, Serialize)]
|
||||
pub enum ProgressMsg {
|
||||
/// Binary data - there may be multiple of these
|
||||
Payload(Vec<u8>),
|
||||
/// Indicates loading is complete, either successfully or not
|
||||
Done(Result<(), String>)
|
||||
Done(SerializableStringResult)
|
||||
}
|
||||
|
||||
/// Convenience function for synchronously loading a whole resource.
|
||||
|
@ -296,8 +301,10 @@ pub fn load_whole_resource(resource_task: &ResourceTask, url: Url)
|
|||
loop {
|
||||
match response.progress_port.recv().unwrap() {
|
||||
ProgressMsg::Payload(data) => buf.push_all(&data),
|
||||
ProgressMsg::Done(Ok(())) => return Ok((response.metadata, buf)),
|
||||
ProgressMsg::Done(Err(e)) => return Err(e)
|
||||
ProgressMsg::Done(SerializableStringResult(Ok(()))) => {
|
||||
return Ok((response.metadata, buf))
|
||||
}
|
||||
ProgressMsg::Done(SerializableStringResult(Err(e))) => return Err(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -321,8 +328,8 @@ impl Iterator for ProgressMsgPortIterator {
|
|||
fn next(&mut self) -> Option<Vec<u8>> {
|
||||
match self.progress_port.recv().unwrap() {
|
||||
ProgressMsg::Payload(data) => Some(data),
|
||||
ProgressMsg::Done(Ok(())) => None,
|
||||
ProgressMsg::Done(Err(e)) => {
|
||||
ProgressMsg::Done(SerializableStringResult(Ok(()))) => None,
|
||||
ProgressMsg::Done(SerializableStringResult(Err(e))) => {
|
||||
error!("error receiving bytes: {}", e);
|
||||
None
|
||||
}
|
||||
|
@ -330,4 +337,226 @@ impl Iterator for ProgressMsgPortIterator {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SerializableMethod(pub Method);
|
||||
|
||||
impl Deref for SerializableMethod {
|
||||
type Target = Method;
|
||||
|
||||
fn deref(&self) -> &Method {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for SerializableMethod {
|
||||
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer {
|
||||
format!("{}", self.0).serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
impl Deserialize for SerializableMethod {
|
||||
fn deserialize<D>(deserializer: &mut D) -> Result<SerializableMethod, D::Error>
|
||||
where D: Deserializer {
|
||||
let string_representation: String = try!(Deserialize::deserialize(deserializer));
|
||||
Ok(SerializableMethod(FromStr::from_str(&string_representation[..]).unwrap()))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SerializableHeaders(pub Headers);
|
||||
|
||||
impl Deref for SerializableHeaders {
|
||||
type Target = Headers;
|
||||
|
||||
fn deref(&self) -> &Headers {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for SerializableHeaders {
|
||||
fn deref_mut(&mut self) -> &mut Headers {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for SerializableHeaders {
|
||||
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer {
|
||||
struct HeadersVisitor<'a> {
|
||||
iter: HeadersItems<'a>,
|
||||
len: usize,
|
||||
}
|
||||
|
||||
impl<'a> ser::MapVisitor for HeadersVisitor<'a> {
|
||||
fn visit<S>(&mut self, serializer: &mut S) -> Result<Option<()>, S::Error>
|
||||
where S: Serializer {
|
||||
match self.iter.next() {
|
||||
Some(header_item) => {
|
||||
try!(serializer.visit_map_elt(header_item.name(),
|
||||
header_item.value_string()));
|
||||
Ok(Some(()))
|
||||
}
|
||||
None => Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
fn len(&self) -> Option<usize> {
|
||||
Some(self.len)
|
||||
}
|
||||
}
|
||||
|
||||
serializer.visit_map(HeadersVisitor {
|
||||
iter: self.iter(),
|
||||
len: self.len(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Deserialize for SerializableHeaders {
|
||||
fn deserialize<D>(deserializer: &mut D) -> Result<SerializableHeaders, D::Error>
|
||||
where D: Deserializer {
|
||||
struct HeadersVisitor;
|
||||
|
||||
impl de::Visitor for HeadersVisitor {
|
||||
type Value = SerializableHeaders;
|
||||
|
||||
fn visit_map<V>(&mut self, mut visitor: V) -> Result<SerializableHeaders, V::Error>
|
||||
where V: de::MapVisitor {
|
||||
let mut result = Headers::new();
|
||||
while let Some((key, value)) = try!(visitor.visit()) {
|
||||
let (key, value): (String, String) = (key, value);
|
||||
result.set_raw(key, vec![value.into_bytes()]);
|
||||
}
|
||||
try!(visitor.end());
|
||||
Ok(SerializableHeaders(result))
|
||||
}
|
||||
}
|
||||
|
||||
let result = SerializableHeaders(Headers::new());
|
||||
try!(deserializer.visit_map(HeadersVisitor));
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||
pub struct SerializableUrl(pub Url);
|
||||
|
||||
impl Deref for SerializableUrl {
|
||||
type Target = Url;
|
||||
|
||||
fn deref(&self) -> &Url {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for SerializableUrl {
|
||||
fn deref_mut(&mut self) -> &mut Url {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for SerializableUrl {
|
||||
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer {
|
||||
format!("{}", self.0).serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
impl Deserialize for SerializableUrl {
|
||||
fn deserialize<D>(deserializer: &mut D) -> Result<SerializableUrl, D::Error>
|
||||
where D: Deserializer {
|
||||
let string_representation: String = try!(Deserialize::deserialize(deserializer));
|
||||
Ok(SerializableUrl(FromStr::from_str(&string_representation[..]).unwrap()))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub struct SerializableContentType(pub ContentType);
|
||||
|
||||
impl Deref for SerializableContentType {
|
||||
type Target = ContentType;
|
||||
|
||||
fn deref(&self) -> &ContentType {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for SerializableContentType {
|
||||
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer {
|
||||
format!("{}", self.0).serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
impl Deserialize for SerializableContentType {
|
||||
fn deserialize<D>(deserializer: &mut D) -> Result<SerializableContentType, D::Error>
|
||||
where D: Deserializer {
|
||||
let string_representation: String = try!(Deserialize::deserialize(deserializer));
|
||||
Ok(SerializableContentType(Header::parse_header(
|
||||
&[string_representation.into_bytes()]).unwrap()))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub struct SerializableRawStatus(pub RawStatus);
|
||||
|
||||
impl Deref for SerializableRawStatus {
|
||||
type Target = RawStatus;
|
||||
|
||||
fn deref(&self) -> &RawStatus {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for SerializableRawStatus {
|
||||
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer {
|
||||
((self.0).0, (self.0).1.clone().into_owned()).serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
impl Deserialize for SerializableRawStatus {
|
||||
fn deserialize<D>(deserializer: &mut D) -> Result<SerializableRawStatus, D::Error>
|
||||
where D: Deserializer {
|
||||
let representation: (u16, String) = try!(Deserialize::deserialize(deserializer));
|
||||
Ok(SerializableRawStatus(RawStatus(representation.0, Cow::Owned(representation.1))))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Debug)]
|
||||
pub struct SerializableStringResult(pub Result<(),String>);
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
enum SerializableStringResultInternal {
|
||||
Ok(()),
|
||||
Err(String),
|
||||
}
|
||||
|
||||
impl Deref for SerializableStringResult {
|
||||
type Target = Result<(),String>;
|
||||
|
||||
fn deref(&self) -> &Result<(),String> {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for SerializableStringResult {
|
||||
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer {
|
||||
let result = match **self {
|
||||
Ok(ref value) => SerializableStringResultInternal::Ok(*value),
|
||||
Err(ref value) => SerializableStringResultInternal::Err((*value).clone()),
|
||||
};
|
||||
result.serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
impl Deserialize for SerializableStringResult {
|
||||
fn deserialize<D>(deserializer: &mut D) -> Result<SerializableStringResult, D::Error>
|
||||
where D: Deserializer {
|
||||
let result: SerializableStringResultInternal =
|
||||
try!(Deserialize::deserialize(deserializer));
|
||||
match result {
|
||||
SerializableStringResultInternal::Ok(value) => Ok(SerializableStringResult(Ok(value))),
|
||||
SerializableStringResultInternal::Err(value) => {
|
||||
Ok(SerializableStringResult(Err(value)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue