minimal implementation of http_network_fetch for testing purposes

This commit is contained in:
Nikki 2015-12-29 16:27:51 -07:00
parent e94a530597
commit af310f7874
4 changed files with 124 additions and 24 deletions

View file

@ -4,16 +4,20 @@
use fetch::cors_cache::{BasicCORSCache, CORSCache, CacheRequestDetails}; use fetch::cors_cache::{BasicCORSCache, CORSCache, CacheRequestDetails};
use fetch::response::ResponseMethods; 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::{Accept, IfMatch, IfRange, IfUnmodifiedSince, Location};
use hyper::header::{AcceptLanguage, ContentLength, ContentLanguage, HeaderView}; 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::{ContentType, Header, Headers, IfModifiedSince, IfNoneMatch};
use hyper::header::{QualityItem, q, qitem, Referer as RefererHeader, UserAgent}; use hyper::header::{QualityItem, q, qitem, Referer as RefererHeader, UserAgent};
use hyper::method::Method; use hyper::method::Method;
use hyper::mime::{Attr, Mime, SubLevel, TopLevel, Value}; use hyper::mime::{Attr, Mime, SubLevel, TopLevel, Value};
use hyper::status::StatusCode; use hyper::status::StatusCode;
use net_traits::{AsyncFetchListener, CacheState, Response}; use net_traits::{AsyncFetchListener, CacheState, HttpsState, Response};
use net_traits::{ResponseType, Metadata}; use net_traits::{ResponseType, Metadata, TerminationReason};
use resource_task::CancellationListener;
use std::ascii::AsciiExt; use std::ascii::AsciiExt;
use std::cell::RefCell; use std::cell::RefCell;
use std::rc::Rc; use std::rc::Rc;
@ -121,7 +125,7 @@ pub struct Request {
pub use_url_credentials: bool, pub use_url_credentials: bool,
pub cache_mode: CacheMode, pub cache_mode: CacheMode,
pub redirect_mode: RedirectMode, pub redirect_mode: RedirectMode,
pub redirect_count: usize, pub redirect_count: u32,
pub response_tainting: ResponseTainting pub response_tainting: ResponseTainting
} }
@ -543,7 +547,6 @@ fn http_fetch(request: Rc<RefCell<Request>>,
fn http_network_or_cache_fetch(request: Rc<RefCell<Request>>, fn http_network_or_cache_fetch(request: Rc<RefCell<Request>>,
credentials_flag: bool, credentials_flag: bool,
authentication_fetch_flag: bool) -> Response { authentication_fetch_flag: bool) -> Response {
// TODO: Implement HTTP network or cache fetch spec
// TODO: Implement Window enum for Request // TODO: Implement Window enum for Request
let request_has_no_window = true; let request_has_no_window = true;
@ -728,7 +731,90 @@ fn http_network_fetch(request: Rc<RefCell<Request>>,
http_request: Rc<RefCell<Request>>, http_request: Rc<RefCell<Request>>,
credentials_flag: bool) -> Response { credentials_flag: bool) -> Response {
// TODO: Implement HTTP network fetch spec // 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::<ContentEncoding>() {
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) /// [CORS preflight fetch](https://fetch.spec.whatwg.org#cors-preflight-fetch)

View file

@ -4,7 +4,7 @@
use hyper::header::Headers; use hyper::header::Headers;
use hyper::status::StatusCode; 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::ascii::AsciiExt;
use std::cell::RefCell; use std::cell::RefCell;
use std::rc::Rc; use std::rc::Rc;
@ -27,6 +27,7 @@ impl ResponseMethods for Response {
headers: Headers::new(), headers: Headers::new(),
body: ResponseBody::Empty, body: ResponseBody::Empty,
cache_state: CacheState::None, cache_state: CacheState::None,
https_state: HttpsState::None,
internal_response: None internal_response: None
} }
} }

View file

@ -198,8 +198,8 @@ pub trait HttpResponse: Read {
} }
struct WrappedHttpResponse { pub struct WrappedHttpResponse {
response: Response pub response: Response
} }
impl Read for WrappedHttpResponse { impl Read for WrappedHttpResponse {
@ -235,8 +235,8 @@ pub trait HttpRequestFactory {
fn create(&self, url: Url, method: Method) -> Result<Self::R, LoadError>; fn create(&self, url: Url, method: Method) -> Result<Self::R, LoadError>;
} }
struct NetworkHttpRequestFactory { pub struct NetworkHttpRequestFactory {
connector: Arc<Pool<Connector>>, pub connector: Arc<Pool<Connector>>,
} }
impl HttpRequestFactory for NetworkHttpRequestFactory { impl HttpRequestFactory for NetworkHttpRequestFactory {
@ -276,7 +276,7 @@ pub trait HttpRequest {
fn send(self, body: &Option<Vec<u8>>) -> Result<Self::R, LoadError>; fn send(self, body: &Option<Vec<u8>>) -> Result<Self::R, LoadError>;
} }
struct WrappedHttpRequest { pub struct WrappedHttpRequest {
request: Request<Fresh> request: Request<Fresh>
} }
@ -556,7 +556,9 @@ pub fn obtain_response<A>(request_factory: &HttpRequestFactory<R=A>,
method: &Method, method: &Method,
request_headers: &mut Headers, request_headers: &mut Headers,
cancel_listener: &CancellationListener, cancel_listener: &CancellationListener,
load_data: &LoadData, data: &Option<Vec<u8>>,
load_data_method: &Method,
pipeline_id: &Option<PipelineId>,
iters: u32, iters: u32,
devtools_chan: &Option<Sender<DevtoolsControlMsg>>, devtools_chan: &Option<Sender<DevtoolsControlMsg>>,
request_id: &str) request_id: &str)
@ -581,7 +583,7 @@ pub fn obtain_response<A>(request_factory: &HttpRequestFactory<R=A>,
for header in req.headers_mut().iter() { for header in req.headers_mut().iter() {
info!(" - {}", header); info!(" - {}", header);
} }
info!("{:?}", load_data.data); info!("{:?}", data);
} }
// Avoid automatically sending request body if a redirect has occurred. // Avoid automatically sending request body if a redirect has occurred.
@ -592,21 +594,21 @@ pub fn obtain_response<A>(request_factory: &HttpRequestFactory<R=A>,
// https://tools.ietf.org/html/rfc7231#section-6.4 // https://tools.ietf.org/html/rfc7231#section-6.4
let is_redirected_request = iters != 1; let is_redirected_request = iters != 1;
let cloned_data; let cloned_data;
let maybe_response = match load_data.data { let maybe_response = match data {
Some(ref data) if !is_redirected_request => { &Some(ref d) if !is_redirected_request => {
req.headers_mut().set(ContentLength(data.len() as u64)); req.headers_mut().set(ContentLength(d.len() as u64));
cloned_data = load_data.data.clone(); cloned_data = data.clone();
req.send(&load_data.data) 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)) req.headers_mut().set(ContentLength(0))
} }
cloned_data = None; cloned_data = None;
req.send(&None) req.send(&None)
} }
}; };
if let Some(pipeline_id) = load_data.pipeline_id { if let Some(pipeline_id) = *pipeline_id {
send_request_to_devtools( send_request_to_devtools(
devtools_chan.clone(), request_id.clone().into(), devtools_chan.clone(), request_id.clone().into(),
url.clone(), method.clone(), request_headers.clone(), url.clone(), method.clone(), request_headers.clone(),
@ -705,7 +707,8 @@ pub fn load<A>(load_data: LoadData,
modify_request_headers(&mut request_headers, &doc_url, &user_agent, &cookie_jar, &load_data); 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, 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); process_response_headers(&response, &url, &doc_url, &cookie_jar, &hsts_list, &load_data);

View file

@ -72,7 +72,7 @@ pub enum ResponseBody {
Done(Vec<u8>), Done(Vec<u8>),
} }
// [Cache state](https://fetch.spec.whatwg.org/#concept-response-cache-state) /// [Cache state](https://fetch.spec.whatwg.org/#concept-response-cache-state)
#[derive(Clone)] #[derive(Clone)]
pub enum CacheState { pub enum CacheState {
None, None,
@ -81,6 +81,14 @@ pub enum CacheState {
Partial Partial
} }
/// [Https state](https://fetch.spec.whatwg.org/#concept-response-https-state)
#[derive(Clone)]
pub enum HttpsState {
None,
Deprecated,
Modern
}
pub enum ResponseMsg { pub enum ResponseMsg {
Chunk(Vec<u8>), Chunk(Vec<u8>),
Finished, Finished,
@ -99,6 +107,7 @@ pub struct Response {
pub headers: Headers, pub headers: Headers,
pub body: ResponseBody, pub body: ResponseBody,
pub cache_state: CacheState, pub cache_state: CacheState,
pub https_state: HttpsState,
/// [Internal response](https://fetch.spec.whatwg.org/#concept-internal-response), only used if the Response /// [Internal response](https://fetch.spec.whatwg.org/#concept-internal-response), only used if the Response
/// is a filtered response /// is a filtered response
pub internal_response: Option<Rc<RefCell<Response>>>, pub internal_response: Option<Rc<RefCell<Response>>>,
@ -115,6 +124,7 @@ impl Response {
headers: Headers::new(), headers: Headers::new(),
body: ResponseBody::Empty, body: ResponseBody::Empty,
cache_state: CacheState::None, cache_state: CacheState::None,
https_state: HttpsState::None,
internal_response: None internal_response: None
} }
} }