servo: Merge #7275 - Initial fetch refactor (from KiChjang:fetch-refactor); r=jdm

Partial #4576
I am really unsure of how things would look like, so would really appreciate some feedback on this.

Source-Repo: https://github.com/servo/servo
Source-Revision: 0fc9410f10c1122a05cd36bdf8b7faff12c39555
This commit is contained in:
Keith Yeung 2015-09-28 13:59:08 -06:00
Родитель 2bfabff31c
Коммит 25b8b342bc
3 изменённых файлов: 104 добавлений и 77 удалений

Просмотреть файл

@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use fetch::cors_cache::{CORSCache, CacheRequestDetails};
use fetch::response::{Response, ResponseType};
use fetch::response::ResponseMethods;
use hyper::header::{Accept, IfMatch, IfRange, IfUnmodifiedSince, Location};
use hyper::header::{AcceptLanguage, ContentLanguage, HeaderView};
use hyper::header::{ContentType, Header, Headers, IfModifiedSince, IfNoneMatch};
@ -11,9 +11,11 @@ use hyper::header::{QualityItem, q, qitem};
use hyper::method::Method;
use hyper::mime::{Attr, Mime, SubLevel, TopLevel, Value};
use hyper::status::StatusCode;
use net_traits::{AsyncFetchListener, Response, ResponseType, Metadata};
use std::ascii::AsciiExt;
use std::str::FromStr;
use url::Url;
use util::task::spawn_named;
/// A [request context](https://fetch.spec.whatwg.org/#concept-request-context)
#[derive(Copy, Clone, PartialEq)]
@ -112,7 +114,7 @@ pub struct Request {
pub redirect_mode: RedirectMode,
pub redirect_count: usize,
pub response_tainting: ResponseTainting,
pub cache: Option<Box<CORSCache + 'static>>
pub cache: Option<Box<CORSCache + Send>>
}
impl Request {
@ -145,6 +147,15 @@ impl Request {
}
}
pub fn fetch_async(mut self,
cors_flag: bool,
listener: Box<AsyncFetchListener + Send>) {
spawn_named(format!("fetch for {:?}", self.url.serialize()), move || {
let res = self.fetch(cors_flag);
listener.response_available(res);
});
}
/// [Fetch](https://fetch.spec.whatwg.org#concept-fetch)
pub fn fetch(&mut self, cors_flag: bool) -> Response {
// Step 1

Просмотреть файл

@ -4,65 +4,18 @@
use hyper::header::Headers;
use hyper::status::StatusCode;
use net_traits::{Response, ResponseBody, ResponseType};
use std::ascii::AsciiExt;
use std::sync::mpsc::Receiver;
use url::Url;
/// [Response type](https://fetch.spec.whatwg.org/#concept-response-type)
#[derive(Clone, PartialEq, Copy)]
pub enum ResponseType {
Basic,
CORS,
Default,
Error,
Opaque
pub trait ResponseMethods {
fn new() -> Response;
fn to_filtered(self, ResponseType) -> Response;
}
/// [Response termination reason](https://fetch.spec.whatwg.org/#concept-response-termination-reason)
#[derive(Clone, Copy)]
pub enum TerminationReason {
EndUserAbort,
Fatal,
Timeout
}
/// The response body can still be pushed to after fetch
/// This provides a way to store unfinished response bodies
#[derive(Clone)]
pub enum ResponseBody {
Empty, // XXXManishearth is this necessary, or is Done(vec![]) enough?
Receiving(Vec<u8>),
Done(Vec<u8>),
}
pub enum ResponseMsg {
Chunk(Vec<u8>),
Finished,
Errored
}
pub struct ResponseLoader {
response: Response,
chan: Receiver<ResponseMsg>
}
/// A [Response](https://fetch.spec.whatwg.org/#concept-response) as defined by the Fetch spec
#[derive(Clone)]
pub struct Response {
pub response_type: ResponseType,
pub termination_reason: Option<TerminationReason>,
pub url: Option<Url>,
/// `None` can be considered a StatusCode of `0`.
pub status: Option<StatusCode>,
pub headers: Headers,
pub body: ResponseBody,
/// [Internal response](https://fetch.spec.whatwg.org/#concept-internal-response), only used if the Response
/// is a filtered response
pub internal_response: Option<Box<Response>>,
}
impl Response {
pub fn new() -> Response {
impl ResponseMethods for Response {
fn new() -> Response {
Response {
response_type: ResponseType::Default,
termination_reason: None,
@ -74,28 +27,9 @@ impl Response {
}
}
pub fn network_error() -> Response {
Response {
response_type: ResponseType::Error,
termination_reason: None,
url: None,
status: None,
headers: Headers::new(),
body: ResponseBody::Empty,
internal_response: None
}
}
pub fn is_network_error(&self) -> bool {
match self.response_type {
ResponseType::Error => true,
_ => false
}
}
/// Convert to a filtered response, of type `filter_type`.
/// Do not use with type Error or Default
pub fn to_filtered(self, filter_type: ResponseType) -> Response {
fn to_filtered(self, filter_type: ResponseType) -> Response {
assert!(filter_type != ResponseType::Error);
assert!(filter_type != ResponseType::Default);
if self.is_network_error() {

Просмотреть файл

@ -5,12 +5,13 @@
#![feature(box_syntax)]
#![feature(custom_attribute)]
#![feature(custom_derive)]
#![feature(box_raw)]
#![feature(plugin)]
#![feature(slice_patterns)]
#![feature(step_by)]
#![feature(vec_push_all)]
#![plugin(plugins, serde_macros)]
#![feature(custom_attribute)]
#![plugin(serde_macros, plugins)]
#![plugin(regex_macros)]
#[macro_use]
@ -30,10 +31,12 @@ use hyper::header::{ContentType, Headers};
use hyper::http::RawStatus;
use hyper::method::Method;
use hyper::mime::{Attr, Mime};
use hyper::status::StatusCode;
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
use msg::constellation_msg::{PipelineId};
use regex::Regex;
use serde::{Deserializer, Serializer};
use std::sync::mpsc::Receiver;
use std::thread;
use url::Url;
use util::mem::HeapSizeOf;
@ -47,6 +50,80 @@ pub static IPV4_REGEX: Regex = regex!(
r"^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$");
pub static IPV6_REGEX: Regex = regex!(r"^([a-fA-F0-9]{0,4}[:]?){1,8}(/\d{1,3})?$");
/// [Response type](https://fetch.spec.whatwg.org/#concept-response-type)
#[derive(Clone, PartialEq, Copy)]
pub enum ResponseType {
Basic,
CORS,
Default,
Error,
Opaque
}
/// [Response termination reason](https://fetch.spec.whatwg.org/#concept-response-termination-reason)
#[derive(Clone, Copy)]
pub enum TerminationReason {
EndUserAbort,
Fatal,
Timeout
}
/// The response body can still be pushed to after fetch
/// This provides a way to store unfinished response bodies
#[derive(Clone)]
pub enum ResponseBody {
Empty, // XXXManishearth is this necessary, or is Done(vec![]) enough?
Receiving(Vec<u8>),
Done(Vec<u8>),
}
pub enum ResponseMsg {
Chunk(Vec<u8>),
Finished,
Errored
}
pub struct ResponseLoader {
response: Response,
chan: Receiver<ResponseMsg>
}
/// A [Response](https://fetch.spec.whatwg.org/#concept-response) as defined by the Fetch spec
#[derive(Clone)]
pub struct Response {
pub response_type: ResponseType,
pub termination_reason: Option<TerminationReason>,
pub url: Option<Url>,
/// `None` can be considered a StatusCode of `0`.
pub status: Option<StatusCode>,
pub headers: Headers,
pub body: ResponseBody,
/// [Internal response](https://fetch.spec.whatwg.org/#concept-internal-response), only used if the Response
/// is a filtered response
pub internal_response: Option<Box<Response>>,
}
impl Response {
pub fn network_error() -> Response {
Response {
response_type: ResponseType::Error,
termination_reason: None,
url: None,
status: None,
headers: Headers::new(),
body: ResponseBody::Empty,
internal_response: None
}
}
pub fn is_network_error(&self) -> bool {
match self.response_type {
ResponseType::Error => true,
_ => false
}
}
}
/// Image handling.
///
/// It may be surprising that this goes in the network crate as opposed to the graphics crate.
@ -85,6 +162,11 @@ impl LoadData {
}
}
/// Interface for observing the final response for an asynchronous fetch operation.
pub trait AsyncFetchListener {
fn response_available(&self, response: Response);
}
/// A listener for asynchronous network events. Cancelling the underlying request is unsupported.
pub trait AsyncResponseListener {
/// The response headers for a request have been received.