Skip to content

Commit

Permalink
Auto merge of #7275 - KiChjang:fetch-refactor, r=jdm
Browse files Browse the repository at this point in the history
Initial fetch refactor

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

<!-- Reviewable:start -->
[<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/7275)
<!-- Reviewable:end -->
  • Loading branch information
bors-servo committed Sep 28, 2015
2 parents a72d7a4 + ecf02a3 commit 0fc9410
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 77 deletions.
15 changes: 13 additions & 2 deletions components/net/fetch/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,19 @@
* 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};
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)]
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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
Expand Down
80 changes: 7 additions & 73 deletions components/net/fetch/response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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() {
Expand Down
86 changes: 84 additions & 2 deletions components/net_traits/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -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;
Expand All @@ -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.
Expand Down Expand Up @@ -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.
Expand Down

0 comments on commit 0fc9410

Please sign in to comment.