diff --git a/components/net/fetch/request.rs b/components/net/fetch/request.rs index 9ca2a6f5d70..8daf650c338 100644 --- a/components/net/fetch/request.rs +++ b/components/net/fetch/request.rs @@ -4,16 +4,20 @@ use fetch::cors_cache::{BasicCORSCache, CORSCache, CacheRequestDetails}; use fetch::response::ResponseMethods; +use http_loader::{NetworkHttpRequestFactory, WrappedHttpResponse}; +use http_loader::{create_http_connector, obtain_response}; +use hyper::client::response::Response as HyperResponse; use hyper::header::{Accept, IfMatch, IfRange, IfUnmodifiedSince, Location}; use hyper::header::{AcceptLanguage, ContentLength, ContentLanguage, HeaderView}; -use hyper::header::{Authorization, Basic}; +use hyper::header::{Authorization, Basic, ContentEncoding, Encoding}; use hyper::header::{ContentType, Header, Headers, IfModifiedSince, IfNoneMatch}; use hyper::header::{QualityItem, q, qitem, Referer as RefererHeader, UserAgent}; use hyper::method::Method; use hyper::mime::{Attr, Mime, SubLevel, TopLevel, Value}; use hyper::status::StatusCode; -use net_traits::{AsyncFetchListener, CacheState, Response}; -use net_traits::{ResponseType, Metadata}; +use net_traits::{AsyncFetchListener, CacheState, HttpsState, Response}; +use net_traits::{ResponseType, Metadata, TerminationReason}; +use resource_task::CancellationListener; use std::ascii::AsciiExt; use std::cell::RefCell; use std::rc::Rc; @@ -121,7 +125,7 @@ pub struct Request { pub use_url_credentials: bool, pub cache_mode: CacheMode, pub redirect_mode: RedirectMode, - pub redirect_count: usize, + pub redirect_count: u32, pub response_tainting: ResponseTainting } @@ -543,7 +547,6 @@ fn http_fetch(request: Rc>, fn http_network_or_cache_fetch(request: Rc>, credentials_flag: bool, authentication_fetch_flag: bool) -> Response { - // TODO: Implement HTTP network or cache fetch spec // TODO: Implement Window enum for Request let request_has_no_window = true; @@ -728,7 +731,90 @@ fn http_network_fetch(request: Rc>, http_request: Rc>, credentials_flag: bool) -> Response { // TODO: Implement HTTP network fetch spec - Response::network_error() + + // Step 1 + // nothing to do here, since credentials_flag is already a boolean + + // Step 2 + // TODO be able to create connection using current url's origin and credentials + let connection = create_http_connector(); + + // Step 3 + // TODO be able to tell if the connection is a failure + + // Step 4 + let factory = NetworkHttpRequestFactory { + connector: connection, + }; + let req = request.borrow(); + let url = req.current_url(); + let cancellation_listener = CancellationListener::new(None); + + let wrapped_response = obtain_response(&factory, &url, &req.method, &mut request.borrow_mut().headers, + &cancellation_listener, &None, &req.method, + &None, req.redirect_count, &None, ""); + + let mut response = Response::new(); + match wrapped_response { + Ok(res) => { + // is it okay for res.version to be unused? + response.url = Some(res.response.url.clone()); + response.status = Some(res.response.status); + response.headers = res.response.headers.clone(); + }, + Err(e) => + response.termination_reason = Some(TerminationReason::Fatal) + }; + + // TODO these substeps aren't possible yet + // Substep 1 + + // Substep 2 + + // TODO how can I tell if response was retrieved over HTTPS? + // TODO: Servo needs to decide what ciphers are to be treated as "deprecated" + response.https_state = HttpsState::None; + + // TODO how do I read request? + + // Step 5 + // TODO when https://bugzilla.mozilla.org/show_bug.cgi?id=1030660 + // is resolved, this step will become uneccesary + // TODO this step + if let Some(encoding) = response.headers.get::() { + if encoding.contains(&Encoding::Gzip) { + + } + + else if encoding.contains(&Encoding::Compress) { + + } + }; + + // Step 6 + response.url_list = request.borrow().url_list.clone(); + + // Step 7 + + // Step 8 + + // Step 9 + // Substep 1 + // Substep 2 + // Substep 3 + // Substep 4 + + // Step 10 + // Substep 1 + // Substep 2 + // Sub-substep 1 + // Sub-substep 2 + // Sub-substep 3 + // Sub-substep 4 + // Substep 3 + + // Step 11 + response } /// [CORS preflight fetch](https://fetch.spec.whatwg.org#cors-preflight-fetch) diff --git a/components/net/fetch/response.rs b/components/net/fetch/response.rs index d236c7da2a3..e0a97d24ca2 100644 --- a/components/net/fetch/response.rs +++ b/components/net/fetch/response.rs @@ -4,7 +4,7 @@ use hyper::header::Headers; use hyper::status::StatusCode; -use net_traits::{CacheState, Response, ResponseBody, ResponseType}; +use net_traits::{CacheState, HttpsState, Response, ResponseBody, ResponseType}; use std::ascii::AsciiExt; use std::cell::RefCell; use std::rc::Rc; @@ -27,6 +27,7 @@ impl ResponseMethods for Response { headers: Headers::new(), body: ResponseBody::Empty, cache_state: CacheState::None, + https_state: HttpsState::None, internal_response: None } } diff --git a/components/net/http_loader.rs b/components/net/http_loader.rs index 995c2e951b1..af05e6c9f27 100644 --- a/components/net/http_loader.rs +++ b/components/net/http_loader.rs @@ -198,8 +198,8 @@ pub trait HttpResponse: Read { } -struct WrappedHttpResponse { - response: Response +pub struct WrappedHttpResponse { + pub response: Response } impl Read for WrappedHttpResponse { @@ -235,8 +235,8 @@ pub trait HttpRequestFactory { fn create(&self, url: Url, method: Method) -> Result; } -struct NetworkHttpRequestFactory { - connector: Arc>, +pub struct NetworkHttpRequestFactory { + pub connector: Arc>, } impl HttpRequestFactory for NetworkHttpRequestFactory { @@ -276,7 +276,7 @@ pub trait HttpRequest { fn send(self, body: &Option>) -> Result; } -struct WrappedHttpRequest { +pub struct WrappedHttpRequest { request: Request } @@ -556,7 +556,9 @@ pub fn obtain_response(request_factory: &HttpRequestFactory, method: &Method, request_headers: &mut Headers, cancel_listener: &CancellationListener, - load_data: &LoadData, + data: &Option>, + load_data_method: &Method, + pipeline_id: &Option, iters: u32, devtools_chan: &Option>, request_id: &str) @@ -581,7 +583,7 @@ pub fn obtain_response(request_factory: &HttpRequestFactory, for header in req.headers_mut().iter() { info!(" - {}", header); } - info!("{:?}", load_data.data); + info!("{:?}", data); } // Avoid automatically sending request body if a redirect has occurred. @@ -592,21 +594,21 @@ pub fn obtain_response(request_factory: &HttpRequestFactory, // https://tools.ietf.org/html/rfc7231#section-6.4 let is_redirected_request = iters != 1; let cloned_data; - let maybe_response = match load_data.data { - Some(ref data) if !is_redirected_request => { - req.headers_mut().set(ContentLength(data.len() as u64)); - cloned_data = load_data.data.clone(); - req.send(&load_data.data) - } + let maybe_response = match data { + &Some(ref d) if !is_redirected_request => { + req.headers_mut().set(ContentLength(d.len() as u64)); + cloned_data = data.clone(); + req.send(data) + }, _ => { - if load_data.method != Method::Get && load_data.method != Method::Head { + if *load_data_method != Method::Get && *load_data_method != Method::Head { req.headers_mut().set(ContentLength(0)) } cloned_data = None; req.send(&None) } }; - if let Some(pipeline_id) = load_data.pipeline_id { + if let Some(pipeline_id) = *pipeline_id { send_request_to_devtools( devtools_chan.clone(), request_id.clone().into(), url.clone(), method.clone(), request_headers.clone(), @@ -705,7 +707,8 @@ pub fn load(load_data: LoadData, modify_request_headers(&mut request_headers, &doc_url, &user_agent, &cookie_jar, &load_data); let response = try!(obtain_response(request_factory, &url, &method, &mut request_headers, - &cancel_listener, &load_data, iters, &devtools_chan, &request_id)); + &cancel_listener, &load_data.data, &load_data.method, + &load_data.pipeline_id, iters, &devtools_chan, &request_id)); process_response_headers(&response, &url, &doc_url, &cookie_jar, &hsts_list, &load_data); diff --git a/components/net_traits/lib.rs b/components/net_traits/lib.rs index 14402b4ede5..44cc15145c3 100644 --- a/components/net_traits/lib.rs +++ b/components/net_traits/lib.rs @@ -72,7 +72,7 @@ pub enum ResponseBody { Done(Vec), } -// [Cache state](https://fetch.spec.whatwg.org/#concept-response-cache-state) +/// [Cache state](https://fetch.spec.whatwg.org/#concept-response-cache-state) #[derive(Clone)] pub enum CacheState { None, @@ -81,6 +81,14 @@ pub enum CacheState { Partial } +/// [Https state](https://fetch.spec.whatwg.org/#concept-response-https-state) +#[derive(Clone)] +pub enum HttpsState { + None, + Deprecated, + Modern +} + pub enum ResponseMsg { Chunk(Vec), Finished, @@ -99,6 +107,7 @@ pub struct Response { pub headers: Headers, pub body: ResponseBody, pub cache_state: CacheState, + pub https_state: HttpsState, /// [Internal response](https://fetch.spec.whatwg.org/#concept-internal-response), only used if the Response /// is a filtered response pub internal_response: Option>>, @@ -115,6 +124,7 @@ impl Response { headers: Headers::new(), body: ResponseBody::Empty, cache_state: CacheState::None, + https_state: HttpsState::None, internal_response: None } }