diff options
-rw-r--r-- | components/net/http_loader.rs | 75 | ||||
-rw-r--r-- | tests/unit/net/http_loader.rs | 547 |
2 files changed, 247 insertions, 375 deletions
diff --git a/components/net/http_loader.rs b/components/net/http_loader.rs index 6578a83b8c2..f27801af52c 100644 --- a/components/net/http_loader.rs +++ b/components/net/http_loader.rs @@ -154,9 +154,9 @@ fn load_for_consumer(load_data: LoadData, let ui_provider = TFDProvider; let context = load_data.context.clone(); - match load::<WrappedHttpRequest, TFDProvider>(load_data, &ui_provider, &http_state, - devtools_chan, &factory, - user_agent, &cancel_listener) { + match load(load_data, &ui_provider, &http_state, + devtools_chan, &factory, + user_agent, &cancel_listener) { Err(LoadError::UnsupportedScheme(url)) => { let s = format!("{} request, but we don't support that scheme", &*url.scheme); send_error(url, s, start_chan) @@ -249,7 +249,7 @@ impl HttpResponse for WrappedHttpResponse { pub trait HttpRequestFactory { type R: HttpRequest; - fn create(&self, url: Url, method: Method) -> Result<Self::R, LoadError>; + fn create(&self, url: Url, method: Method, headers: Headers) -> Result<Self::R, LoadError>; } pub struct NetworkHttpRequestFactory { @@ -259,7 +259,8 @@ pub struct NetworkHttpRequestFactory { impl HttpRequestFactory for NetworkHttpRequestFactory { type R = WrappedHttpRequest; - fn create(&self, url: Url, method: Method) -> Result<WrappedHttpRequest, LoadError> { + fn create(&self, url: Url, method: Method, headers: Headers) + -> Result<WrappedHttpRequest, LoadError> { let connection = Request::with_connector(method, url.clone(), &*self.connector); if let Err(HttpError::Ssl(ref error)) = connection { @@ -274,13 +275,14 @@ impl HttpRequestFactory for NetworkHttpRequestFactory { } } - let request = match connection { + let mut request = match connection { Ok(req) => req, Err(e) => { return Err(LoadError::Connection(url, e.description().to_owned())) } }; + *request.headers_mut() = headers; Ok(WrappedHttpRequest { request: request }) } @@ -289,7 +291,6 @@ impl HttpRequestFactory for NetworkHttpRequestFactory { pub trait HttpRequest { type R: HttpResponse + 'static; - fn headers_mut(&mut self) -> &mut Headers; fn send(self, body: &Option<Vec<u8>>) -> Result<Self::R, LoadError>; } @@ -300,10 +301,6 @@ pub struct WrappedHttpRequest { impl HttpRequest for WrappedHttpRequest { type R = WrappedHttpResponse; - fn headers_mut(&mut self) -> &mut Headers { - self.request.headers_mut() - } - fn send(self, body: &Option<Vec<u8>>) -> Result<WrappedHttpResponse, LoadError> { let url = self.request.url.clone(); let mut request_writer = match self.request.start() { @@ -628,6 +625,7 @@ pub fn obtain_response<A>(request_factory: &HttpRequestFactory<R=A>, request_id: &str) -> Result<A::R, LoadError> where A: HttpRequest + 'static { + let null_data = None; let response; let connection_url = replace_hosts(&url); @@ -636,20 +634,7 @@ pub fn obtain_response<A>(request_factory: &HttpRequestFactory<R=A>, // a ConnectionAborted error. this loop tries again with a new // connection. loop { - let mut req = try!(request_factory.create(connection_url.clone(), method.clone())); - *req.headers_mut() = request_headers.clone(); - - if cancel_listener.is_cancelled() { - return Err(LoadError::Cancelled(connection_url.clone(), "load cancelled".to_owned())); - } - - if log_enabled!(log::LogLevel::Info) { - info!("{}", method); - for header in req.headers_mut().iter() { - info!(" - {}", header); - } - info!("{:?}", data); - } + let mut headers = request_headers.clone(); // Avoid automatically sending request body if a redirect has occurred. // @@ -658,26 +643,42 @@ pub fn obtain_response<A>(request_factory: &HttpRequestFactory<R=A>, // // https://tools.ietf.org/html/rfc7231#section-6.4 let is_redirected_request = iters != 1; - let cloned_data; - let maybe_response = match data { + let request_body; + 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) - }, + headers.set(ContentLength(d.len() as u64)); + request_body = data; + } _ => { if *load_data_method != Method::Get && *load_data_method != Method::Head { - req.headers_mut().set(ContentLength(0)) + headers.set(ContentLength(0)) } - cloned_data = None; - req.send(&None) + request_body = &null_data; } - }; + } + + if log_enabled!(log::LogLevel::Info) { + info!("{}", method); + for header in headers.iter() { + info!(" - {}", header); + } + info!("{:?}", data); + } + + let req = try!(request_factory.create(connection_url.clone(), method.clone(), + headers.clone())); + + if cancel_listener.is_cancelled() { + return Err(LoadError::Cancelled(connection_url.clone(), "load cancelled".to_owned())); + } + + let maybe_response = req.send(request_body); + 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(), - cloned_data, pipeline_id, time::now() + url.clone(), method.clone(), headers, + request_body.clone(), pipeline_id, time::now() ); } diff --git a/tests/unit/net/http_loader.rs b/tests/unit/net/http_loader.rs index 10aa01d3e4c..e599de3febe 100644 --- a/tests/unit/net/http_loader.rs +++ b/tests/unit/net/http_loader.rs @@ -113,10 +113,9 @@ impl UIProvider for TestProvider { } } -fn basic_auth(headers: Headers) -> MockResponse { - +fn basic_auth() -> MockResponse { MockResponse::new( - headers, + Headers::new(), StatusCode::Unauthorized, RawStatus(401, Cow::Borrowed("Unauthorized")), b"".to_vec() @@ -138,17 +137,17 @@ enum ResponseType { Redirect(String), RedirectWithHeaders(String, Headers), Text(Vec<u8>), - WithHeaders(Vec<u8>, Headers) + WithHeaders(Vec<u8>, Headers), + NeedsAuth, } struct MockRequest { - headers: Headers, t: ResponseType } impl MockRequest { fn new(t: ResponseType) -> MockRequest { - MockRequest { headers: Headers::new(), t: t } + MockRequest { t: t } } } @@ -165,6 +164,9 @@ fn response_for_request_type(t: ResponseType) -> Result<MockResponse, LoadError> }, ResponseType::WithHeaders(b, h) => { Ok(respond_with_headers(b, h)) + }, + ResponseType::NeedsAuth => { + Ok(basic_auth()) } } } @@ -172,109 +174,7 @@ fn response_for_request_type(t: ResponseType) -> Result<MockResponse, LoadError> impl HttpRequest for MockRequest { type R = MockResponse; - fn headers_mut(&mut self) -> &mut Headers { &mut self.headers } - - fn send(self, _: &Option<Vec<u8>>) -> Result<MockResponse, LoadError> { - response_for_request_type(self.t) - } -} - -struct AssertRequestMustHaveHeaders { - expected_headers: Headers, - request_headers: Headers, - t: ResponseType -} - -impl AssertRequestMustHaveHeaders { - fn new(t: ResponseType, expected_headers: Headers) -> Self { - AssertRequestMustHaveHeaders { expected_headers: expected_headers, request_headers: Headers::new(), t: t } - } -} - -impl HttpRequest for AssertRequestMustHaveHeaders { - type R = MockResponse; - - fn headers_mut(&mut self) -> &mut Headers { &mut self.request_headers } - - fn send(self, _: &Option<Vec<u8>>) -> Result<MockResponse, LoadError> { - assert_eq!(self.request_headers, self.expected_headers); - response_for_request_type(self.t) - } -} - -struct AssertAuthHeaderRequest { - expected_headers: Headers, - request_headers: Headers, - t: ResponseType -} - -impl AssertAuthHeaderRequest { - fn new(t: ResponseType, expected_headers: Headers) -> Self { - AssertAuthHeaderRequest { expected_headers: expected_headers, request_headers: Headers::new(), t: t } - } -} - -impl HttpRequest for AssertAuthHeaderRequest { - type R = MockResponse; - - fn headers_mut(&mut self) -> &mut Headers { &mut self.request_headers } - - fn send(self, _: &Option<Vec<u8>>) -> Result<MockResponse, LoadError> { - - if self.request_headers.has::<Authorization<Basic>>() { - for header in self.expected_headers.iter() { - assert!(self.request_headers.get_raw(header.name()).is_some()); - assert_eq!( - self.request_headers.get_raw(header.name()).unwrap(), - self.expected_headers.get_raw(header.name()).unwrap() - ) - } - response_for_request_type(self.t) - } else { - Ok(basic_auth(self.request_headers)) - } - } -} - -struct AssertRequestMustIncludeHeaders { - expected_headers: Headers, - request_headers: Headers, - t: ResponseType -} - -impl AssertRequestMustIncludeHeaders { - fn new(t: ResponseType, expected_headers_op: Option<Headers>) -> Self { - match expected_headers_op { - Some(expected_headers) => { - assert!(expected_headers.len() != 0); - AssertRequestMustIncludeHeaders { - expected_headers: expected_headers, - request_headers: Headers::new(), - t: t - } - } - None => AssertRequestMustIncludeHeaders { - expected_headers: Headers::new(), - request_headers: Headers::new(), - t: t - } - } - } -} - -impl HttpRequest for AssertRequestMustIncludeHeaders { - type R = MockResponse; - - fn headers_mut(&mut self) -> &mut Headers { &mut self.request_headers } - fn send(self, _: &Option<Vec<u8>>) -> Result<MockResponse, LoadError> { - for header in self.expected_headers.iter() { - assert!(self.request_headers.get_raw(header.name()).is_some()); - assert_eq!( - self.request_headers.get_raw(header.name()).unwrap(), - self.expected_headers.get_raw(header.name()).unwrap() - ) - } response_for_request_type(self.t) } } @@ -285,15 +185,11 @@ struct AssertMustHaveHeadersRequestFactory { } impl HttpRequestFactory for AssertMustHaveHeadersRequestFactory { - type R = AssertRequestMustHaveHeaders; + type R = MockRequest; - fn create(&self, _: Url, _: Method) -> Result<AssertRequestMustHaveHeaders, LoadError> { - Ok( - AssertRequestMustHaveHeaders::new( - ResponseType::Text(self.body.clone()), - self.expected_headers.clone() - ) - ) + fn create(&self, _: Url, _: Method, headers: Headers) -> Result<MockRequest, LoadError> { + assert_eq!(headers, self.expected_headers); + Ok(MockRequest::new(ResponseType::Text(self.body.clone()))) } } @@ -303,15 +199,26 @@ struct AssertAuthHeaderRequestFactory { } impl HttpRequestFactory for AssertAuthHeaderRequestFactory { - type R = AssertAuthHeaderRequest; + type R = MockRequest; - fn create(&self, _: Url, _: Method) -> Result<AssertAuthHeaderRequest, LoadError> { - Ok( - AssertAuthHeaderRequest::new( - ResponseType::Text(self.body.clone()), - self.expected_headers.clone() - ) - ) + fn create(&self, _: Url, _: Method, headers: Headers) -> Result<MockRequest, LoadError> { + let request = if headers.has::<Authorization<Basic>>() { + assert_headers_included(&self.expected_headers, &headers); + MockRequest::new(ResponseType::Text(self.body.clone())) + } else { + MockRequest::new(ResponseType::NeedsAuth) + }; + + Ok(request) + } +} + +fn assert_headers_included(expected: &Headers, request: &Headers) { + assert!(expected.len() != 0); + for header in expected.iter() { + assert!(request.get_raw(header.name()).is_some()); + assert_eq!(request.get_raw(header.name()).unwrap(), + expected.get_raw(header.name()).unwrap()) } } @@ -321,15 +228,11 @@ struct AssertMustIncludeHeadersRequestFactory { } impl HttpRequestFactory for AssertMustIncludeHeadersRequestFactory { - type R = AssertRequestMustIncludeHeaders; + type R = MockRequest; - fn create(&self, _: Url, _: Method) -> Result<AssertRequestMustIncludeHeaders, LoadError> { - Ok( - AssertRequestMustIncludeHeaders::new( - ResponseType::Text(self.body.clone()), - Some(self.expected_headers.clone()) - ) - ) + fn create(&self, _: Url, _: Method, headers: Headers) -> Result<MockRequest, LoadError> { + assert_headers_included(&self.expected_headers, &headers); + Ok(MockRequest::new(ResponseType::Text(self.body.clone()))) } } @@ -345,70 +248,38 @@ fn assert_cookie_for_domain(cookie_jar: Arc<RwLock<CookieStorage>>, domain: &str } } -struct AssertRequestMustNotIncludeHeaders { - headers_not_expected: Vec<String>, - request_headers: Headers, - t: ResponseType -} - -impl AssertRequestMustNotIncludeHeaders { - fn new(t: ResponseType, headers_not_expected: Vec<String>) -> Self { - assert!(headers_not_expected.len() != 0); - AssertRequestMustNotIncludeHeaders { - headers_not_expected: headers_not_expected, - request_headers: Headers::new(), t: t } - } -} - -impl HttpRequest for AssertRequestMustNotIncludeHeaders { - type R = MockResponse; - - fn headers_mut(&mut self) -> &mut Headers { &mut self.request_headers } - - fn send(self, _: &Option<Vec<u8>>) -> Result<MockResponse, LoadError> { - for header in &self.headers_not_expected { - assert!(self.request_headers.get_raw(header).is_none()); - } - - response_for_request_type(self.t) - } -} - struct AssertMustNotIncludeHeadersRequestFactory { headers_not_expected: Vec<String>, body: Vec<u8> } impl HttpRequestFactory for AssertMustNotIncludeHeadersRequestFactory { - type R = AssertRequestMustNotIncludeHeaders; + type R = MockRequest; - fn create(&self, _: Url, _: Method) -> Result<AssertRequestMustNotIncludeHeaders, LoadError> { - Ok( - AssertRequestMustNotIncludeHeaders::new( - ResponseType::Text(self.body.clone()), - self.headers_not_expected.clone() - ) - ) + fn create(&self, _: Url, _: Method, headers: Headers) -> Result<MockRequest, LoadError> { + assert!(self.headers_not_expected.len() != 0); + for header in &self.headers_not_expected { + assert!(headers.get_raw(header).is_none()); + } + + Ok(MockRequest::new(ResponseType::Text(self.body.clone()))) } } struct AssertMustHaveBodyRequest { expected_body: Option<Vec<u8>>, - headers: Headers, t: ResponseType } impl AssertMustHaveBodyRequest { fn new(t: ResponseType, expected_body: Option<Vec<u8>>) -> Self { - AssertMustHaveBodyRequest { expected_body: expected_body, headers: Headers::new(), t: t } + AssertMustHaveBodyRequest { expected_body: expected_body, t: t } } } impl HttpRequest for AssertMustHaveBodyRequest { type R = MockResponse; - fn headers_mut(&mut self) -> &mut Headers { &mut self.headers } - fn send(self, body: &Option<Vec<u8>>) -> Result<MockResponse, LoadError> { assert_eq!(self.expected_body, *body); @@ -474,22 +345,22 @@ fn test_check_default_headers_loaded_in_every_request() { headers.set(UserAgent(DEFAULT_USER_AGENT.to_owned())); // Testing for method.GET - let _ = load::<AssertRequestMustHaveHeaders, TestProvider>(load_data.clone(), &ui_provider, &http_state, None, - &AssertMustHaveHeadersRequestFactory { - expected_headers: headers.clone(), - body: <[_]>::to_vec(&[]) - }, DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None)); + let _ = load(load_data.clone(), &ui_provider, &http_state, None, + &AssertMustHaveHeadersRequestFactory { + expected_headers: headers.clone(), + body: <[_]>::to_vec(&[]) + }, DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None)); // Testing for method.POST load_data.method = Method::Post; headers.set(ContentLength(0 as u64)); - let _ = load::<AssertRequestMustHaveHeaders, TestProvider>(load_data.clone(), &ui_provider, &http_state, None, - &AssertMustHaveHeadersRequestFactory { - expected_headers: headers, - body: <[_]>::to_vec(&[]) - }, DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None)); + let _ = load(load_data.clone(), &ui_provider, &http_state, None, + &AssertMustHaveHeadersRequestFactory { + expected_headers: headers, + body: <[_]>::to_vec(&[]) + }, DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None)); } #[test] @@ -506,7 +377,7 @@ fn test_load_when_request_is_not_get_or_head_and_there_is_no_body_content_length let mut content_length = Headers::new(); content_length.set(ContentLength(0)); - let _ = load::<AssertRequestMustIncludeHeaders, TestProvider>( + let _ = load( load_data.clone(), &ui_provider, &http_state, None, &AssertMustIncludeHeadersRequestFactory { expected_headers: content_length, @@ -521,7 +392,7 @@ fn test_request_and_response_data_with_network_messages() { impl HttpRequestFactory for Factory { type R = MockRequest; - fn create(&self, _: Url, _: Method) -> Result<MockRequest, LoadError> { + fn create(&self, _: Url, _: Method, _: Headers) -> Result<MockRequest, LoadError> { let mut headers = Headers::new(); headers.set(Host { hostname: "foo.bar".to_owned(), port: None }); Ok(MockRequest::new( @@ -541,8 +412,8 @@ fn test_request_and_response_data_with_network_messages() { let mut request_headers = Headers::new(); request_headers.set(Host { hostname: "bar.foo".to_owned(), port: None }); load_data.headers = request_headers.clone(); - let _ = load::<MockRequest, TestProvider>(load_data, &ui_provider, &http_state, Some(devtools_chan), &Factory, - DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None)); + let _ = load(load_data, &ui_provider, &http_state, Some(devtools_chan), &Factory, + DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None)); // notification received from devtools let devhttprequest = expect_devtools_http_request(&devtools_port); @@ -596,7 +467,7 @@ fn test_request_and_response_message_from_devtool_without_pipeline_id() { impl HttpRequestFactory for Factory { type R = MockRequest; - fn create(&self, _: Url, _: Method) -> Result<MockRequest, LoadError> { + fn create(&self, _: Url, _: Method, _: Headers) -> Result<MockRequest, LoadError> { let mut headers = Headers::new(); headers.set(Host { hostname: "foo.bar".to_owned(), port: None }); Ok(MockRequest::new( @@ -611,8 +482,8 @@ fn test_request_and_response_message_from_devtool_without_pipeline_id() { let url = Url::parse("https://mozilla.com").unwrap(); let (devtools_chan, devtools_port) = mpsc::channel::<DevtoolsControlMsg>(); let load_data = LoadData::new(LoadContext::Browsing, url.clone(), None); - let _ = load::<MockRequest, TestProvider>(load_data, &ui_provider, &http_state, Some(devtools_chan), &Factory, - DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None)); + let _ = load(load_data, &ui_provider, &http_state, Some(devtools_chan), &Factory, + DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None)); // notification received from devtools assert!(devtools_port.try_recv().is_err()); @@ -627,7 +498,7 @@ fn test_load_when_redirecting_from_a_post_should_rewrite_next_request_as_get() { impl HttpRequestFactory for Factory { type R = MockRequest; - fn create(&self, url: Url, method: Method) -> Result<MockRequest, LoadError> { + fn create(&self, url: Url, method: Method, _: Headers) -> Result<MockRequest, LoadError> { if url.domain().unwrap() == "mozilla.com" { assert_eq!(Method::Post, method); Ok(MockRequest::new(ResponseType::Redirect("http://mozilla.org".to_owned()))) @@ -645,8 +516,8 @@ fn test_load_when_redirecting_from_a_post_should_rewrite_next_request_as_get() { let http_state = HttpState::new(); let ui_provider = TestProvider::new(); - let _ = load::<MockRequest, TestProvider>(load_data, &ui_provider, &http_state, None, &Factory, - DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None)); + let _ = load(load_data, &ui_provider, &http_state, None, &Factory, + DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None)); } #[test] @@ -656,7 +527,7 @@ fn test_load_should_decode_the_response_as_deflate_when_response_headers_have_co impl HttpRequestFactory for Factory { type R = MockRequest; - fn create(&self, _: Url, _: Method) -> Result<MockRequest, LoadError> { + fn create(&self, _: Url, _: Method, _: Headers) -> Result<MockRequest, LoadError> { let mut e = DeflateEncoder::new(Vec::new(), Compression::Default); e.write(b"Yay!").unwrap(); let encoded_content = e.finish().unwrap(); @@ -673,7 +544,7 @@ fn test_load_should_decode_the_response_as_deflate_when_response_headers_have_co let http_state = HttpState::new(); let ui_provider = TestProvider::new(); - let mut response = load::<MockRequest, TestProvider>( + let mut response = load( load_data, &ui_provider, &http_state, None, &Factory, DEFAULT_USER_AGENT.to_owned(), @@ -690,7 +561,7 @@ fn test_load_should_decode_the_response_as_gzip_when_response_headers_have_conte impl HttpRequestFactory for Factory { type R = MockRequest; - fn create(&self, _: Url, _: Method) -> Result<MockRequest, LoadError> { + fn create(&self, _: Url, _: Method, _: Headers) -> Result<MockRequest, LoadError> { let mut e = GzEncoder::new(Vec::new(), Compression::Default); e.write(b"Yay!").unwrap(); let encoded_content = e.finish().unwrap(); @@ -706,7 +577,7 @@ fn test_load_should_decode_the_response_as_gzip_when_response_headers_have_conte let http_state = HttpState::new(); let ui_provider = TestProvider::new(); - let mut response = load::<MockRequest, TestProvider>( + let mut response = load( load_data, &ui_provider, &http_state, None, &Factory, @@ -724,7 +595,7 @@ fn test_load_doesnt_send_request_body_on_any_redirect() { impl HttpRequestFactory for Factory { type R = AssertMustHaveBodyRequest; - fn create(&self, url: Url, _: Method) -> Result<AssertMustHaveBodyRequest, LoadError> { + fn create(&self, url: Url, _: Method, _: Headers) -> Result<AssertMustHaveBodyRequest, LoadError> { if url.domain().unwrap() == "mozilla.com" { Ok( AssertMustHaveBodyRequest::new( @@ -750,7 +621,7 @@ fn test_load_doesnt_send_request_body_on_any_redirect() { let http_state = HttpState::new(); let ui_provider = TestProvider::new(); - let _ = load::<AssertMustHaveBodyRequest, TestProvider>( + let _ = load( load_data, &ui_provider, &http_state, None, &Factory, @@ -765,7 +636,7 @@ fn test_load_doesnt_add_host_to_sts_list_when_url_is_http_even_if_sts_headers_ar impl HttpRequestFactory for Factory { type R = MockRequest; - fn create(&self, _: Url, _: Method) -> Result<MockRequest, LoadError> { + fn create(&self, _: Url, _: Method, _: Headers) -> Result<MockRequest, LoadError> { let content = <[_]>::to_vec("Yay!".as_bytes()); let mut headers = Headers::new(); headers.set(StrictTransportSecurity::excluding_subdomains(31536000)); @@ -780,12 +651,12 @@ fn test_load_doesnt_add_host_to_sts_list_when_url_is_http_even_if_sts_headers_ar let http_state = HttpState::new(); let ui_provider = TestProvider::new(); - let _ = load::<MockRequest, TestProvider>(load_data, - &ui_provider, &http_state, - None, - &Factory, - DEFAULT_USER_AGENT.to_owned(), - &CancellationListener::new(None)); + let _ = load(load_data, + &ui_provider, &http_state, + None, + &Factory, + DEFAULT_USER_AGENT.to_owned(), + &CancellationListener::new(None)); assert_eq!(http_state.hsts_list.read().unwrap().is_host_secure("mozilla.com"), false); } @@ -797,7 +668,7 @@ fn test_load_adds_host_to_sts_list_when_url_is_https_and_sts_headers_are_present impl HttpRequestFactory for Factory { type R = MockRequest; - fn create(&self, _: Url, _: Method) -> Result<MockRequest, LoadError> { + fn create(&self, _: Url, _: Method, _: Headers) -> Result<MockRequest, LoadError> { let content = <[_]>::to_vec("Yay!".as_bytes()); let mut headers = Headers::new(); headers.set(StrictTransportSecurity::excluding_subdomains(31536000)); @@ -812,12 +683,12 @@ fn test_load_adds_host_to_sts_list_when_url_is_https_and_sts_headers_are_present let http_state = HttpState::new(); let ui_provider = TestProvider::new(); - let _ = load::<MockRequest, TestProvider>(load_data, - &ui_provider, &http_state, - None, - &Factory, - DEFAULT_USER_AGENT.to_owned(), - &CancellationListener::new(None)); + let _ = load(load_data, + &ui_provider, &http_state, + None, + &Factory, + DEFAULT_USER_AGENT.to_owned(), + &CancellationListener::new(None)); assert!(http_state.hsts_list.read().unwrap().is_host_secure("mozilla.com")); } @@ -829,7 +700,7 @@ fn test_load_sets_cookies_in_the_resource_manager_when_it_get_set_cookie_header_ impl HttpRequestFactory for Factory { type R = MockRequest; - fn create(&self, _: Url, _: Method) -> Result<MockRequest, LoadError> { + fn create(&self, _: Url, _: Method, _: Headers) -> Result<MockRequest, LoadError> { let content = <[_]>::to_vec("Yay!".as_bytes()); let mut headers = Headers::new(); headers.set(SetCookie(vec![CookiePair::new("mozillaIs".to_owned(), "theBest".to_owned())])); @@ -846,12 +717,12 @@ fn test_load_sets_cookies_in_the_resource_manager_when_it_get_set_cookie_header_ let load_data = LoadData::new(LoadContext::Browsing, url.clone(), None); - let _ = load::<MockRequest, TestProvider>(load_data, - &ui_provider, &http_state, - None, - &Factory, - DEFAULT_USER_AGENT.to_owned(), - &CancellationListener::new(None)); + let _ = load(load_data, + &ui_provider, &http_state, + None, + &Factory, + DEFAULT_USER_AGENT.to_owned(), + &CancellationListener::new(None)); assert_cookie_for_domain(http_state.cookie_jar.clone(), "http://mozilla.com", "mozillaIs=theBest"); } @@ -880,12 +751,12 @@ fn test_load_sets_requests_cookies_header_for_url_by_getting_cookies_from_the_re let mut cookie = Headers::new(); cookie.set(CookieHeader(vec![CookiePair::new("mozillaIs".to_owned(), "theBest".to_owned())])); - let _ = load::<AssertRequestMustIncludeHeaders, TestProvider>(load_data.clone(), &ui_provider, &http_state, None, - &AssertMustIncludeHeadersRequestFactory { - expected_headers: cookie, - body: <[_]>::to_vec(&*load_data.data.unwrap()) - }, DEFAULT_USER_AGENT.to_owned(), - &CancellationListener::new(None)); + let _ = load(load_data.clone(), &ui_provider, &http_state, None, + &AssertMustIncludeHeadersRequestFactory { + expected_headers: cookie, + body: <[_]>::to_vec(&*load_data.data.unwrap()) + }, DEFAULT_USER_AGENT.to_owned(), + &CancellationListener::new(None)); } #[test] @@ -922,7 +793,7 @@ fn test_load_sends_secure_cookie_if_http_changed_to_https_due_to_entry_in_hsts_s let mut headers = Headers::new(); headers.set_raw("Cookie".to_owned(), vec![<[_]>::to_vec("mozillaIs=theBest".as_bytes())]); - let _ = load::<AssertRequestMustIncludeHeaders, TestProvider>( + let _ = load( load_data.clone(), &ui_provider, &http_state, None, &AssertMustIncludeHeadersRequestFactory { expected_headers: headers, @@ -954,7 +825,7 @@ fn test_load_sends_cookie_if_nonhttp() { let mut headers = Headers::new(); headers.set_raw("Cookie".to_owned(), vec![<[_]>::to_vec("mozillaIs=theBest".as_bytes())]); - let _ = load::<AssertRequestMustIncludeHeaders, TestProvider>( + let _ = load( load_data.clone(), &ui_provider, &http_state, None, &AssertMustIncludeHeadersRequestFactory { expected_headers: headers, @@ -969,7 +840,7 @@ fn test_cookie_set_with_httponly_should_not_be_available_using_getcookiesforurl( impl HttpRequestFactory for Factory { type R = MockRequest; - fn create(&self, _: Url, _: Method) -> Result<MockRequest, LoadError> { + fn create(&self, _: Url, _: Method, _: Headers) -> Result<MockRequest, LoadError> { let content = <[_]>::to_vec("Yay!".as_bytes()); let mut headers = Headers::new(); headers.set_raw("set-cookie", vec![b"mozillaIs=theBest; HttpOnly;".to_vec()]); @@ -983,12 +854,12 @@ fn test_cookie_set_with_httponly_should_not_be_available_using_getcookiesforurl( let ui_provider = TestProvider::new(); let load_data = LoadData::new(LoadContext::Browsing, url.clone(), None); - let _ = load::<MockRequest, TestProvider>(load_data, - &ui_provider, &http_state, - None, - &Factory, - DEFAULT_USER_AGENT.to_owned(), - &CancellationListener::new(None)); + let _ = load(load_data, + &ui_provider, &http_state, + None, + &Factory, + DEFAULT_USER_AGENT.to_owned(), + &CancellationListener::new(None)); let mut cookie_jar = http_state.cookie_jar.write().unwrap(); assert!(cookie_jar.cookies_for_url(&url, CookieSource::NonHTTP).is_none()); @@ -1001,7 +872,7 @@ fn test_when_cookie_received_marked_secure_is_ignored_for_http() { impl HttpRequestFactory for Factory { type R = MockRequest; - fn create(&self, _: Url, _: Method) -> Result<MockRequest, LoadError> { + fn create(&self, _: Url, _: Method, _: Headers) -> Result<MockRequest, LoadError> { let content = <[_]>::to_vec("Yay!".as_bytes()); let mut headers = Headers::new(); headers.set_raw("set-cookie", vec![b"mozillaIs=theBest; Secure;".to_vec()]); @@ -1013,12 +884,12 @@ fn test_when_cookie_received_marked_secure_is_ignored_for_http() { let ui_provider = TestProvider::new(); let load_data = LoadData::new(LoadContext::Browsing, Url::parse("http://mozilla.com").unwrap(), None); - let _ = load::<MockRequest, TestProvider>(load_data, - &ui_provider, &http_state, - None, - &Factory, - DEFAULT_USER_AGENT.to_owned(), - &CancellationListener::new(None)); + let _ = load(load_data, + &ui_provider, &http_state, + None, + &Factory, + DEFAULT_USER_AGENT.to_owned(), + &CancellationListener::new(None)); assert_cookie_for_domain(http_state.cookie_jar.clone(), "http://mozilla.com", ""); } @@ -1048,7 +919,7 @@ fn test_when_cookie_set_marked_httpsonly_secure_isnt_sent_on_http_request() { assert_cookie_for_domain(http_state.cookie_jar.clone(), "https://mozilla.com", "mozillaIs=theBest"); - let _ = load::<AssertRequestMustNotIncludeHeaders, TestProvider>( + let _ = load( load_data.clone(), &ui_provider, &http_state, None, &AssertMustNotIncludeHeadersRequestFactory { headers_not_expected: vec!["Cookie".to_owned()], @@ -1070,12 +941,12 @@ fn test_load_sets_content_length_to_length_of_request_body() { let http_state = HttpState::new(); let ui_provider = TestProvider::new(); - let _ = load::<AssertRequestMustIncludeHeaders, TestProvider>(load_data.clone(), &ui_provider, &http_state, - None, &AssertMustIncludeHeadersRequestFactory { - expected_headers: content_len_headers, - body: <[_]>::to_vec(&*load_data.data.unwrap()) - }, DEFAULT_USER_AGENT.to_owned(), - &CancellationListener::new(None)); + let _ = load(load_data.clone(), &ui_provider, &http_state, + None, &AssertMustIncludeHeadersRequestFactory { + expected_headers: content_len_headers, + body: <[_]>::to_vec(&*load_data.data.unwrap()) + }, DEFAULT_USER_AGENT.to_owned(), + &CancellationListener::new(None)); } #[test] @@ -1093,14 +964,14 @@ fn test_load_uses_explicit_accept_from_headers_in_load_data() { let http_state = HttpState::new(); let ui_provider = TestProvider::new(); - let _ = load::<AssertRequestMustIncludeHeaders, TestProvider>(load_data, - &ui_provider, &http_state, - None, - &AssertMustIncludeHeadersRequestFactory { - expected_headers: accept_headers, - body: <[_]>::to_vec("Yay!".as_bytes()) - }, DEFAULT_USER_AGENT.to_owned(), - &CancellationListener::new(None)); + let _ = load(load_data, + &ui_provider, &http_state, + None, + &AssertMustIncludeHeadersRequestFactory { + expected_headers: accept_headers, + body: <[_]>::to_vec("Yay!".as_bytes()) + }, DEFAULT_USER_AGENT.to_owned(), + &CancellationListener::new(None)); } #[test] @@ -1120,14 +991,14 @@ fn test_load_sets_default_accept_to_html_xhtml_xml_and_then_anything_else() { let http_state = HttpState::new(); let ui_provider = TestProvider::new(); - let _ = load::<AssertRequestMustIncludeHeaders, TestProvider>(load_data, - &ui_provider, &http_state, - None, - &AssertMustIncludeHeadersRequestFactory { - expected_headers: accept_headers, - body: <[_]>::to_vec("Yay!".as_bytes()) - }, DEFAULT_USER_AGENT.to_owned(), - &CancellationListener::new(None)); + let _ = load(load_data, + &ui_provider, &http_state, + None, + &AssertMustIncludeHeadersRequestFactory { + expected_headers: accept_headers, + body: <[_]>::to_vec("Yay!".as_bytes()) + }, DEFAULT_USER_AGENT.to_owned(), + &CancellationListener::new(None)); } #[test] @@ -1143,14 +1014,14 @@ fn test_load_uses_explicit_accept_encoding_from_load_data_headers() { let http_state = HttpState::new(); let ui_provider = TestProvider::new(); - let _ = load::<AssertRequestMustIncludeHeaders, TestProvider>(load_data, - &ui_provider, &http_state, - None, - &AssertMustIncludeHeadersRequestFactory { - expected_headers: accept_encoding_headers, - body: <[_]>::to_vec("Yay!".as_bytes()) - }, DEFAULT_USER_AGENT.to_owned(), - &CancellationListener::new(None)); + let _ = load(load_data, + &ui_provider, &http_state, + None, + &AssertMustIncludeHeadersRequestFactory { + expected_headers: accept_encoding_headers, + body: <[_]>::to_vec("Yay!".as_bytes()) + }, DEFAULT_USER_AGENT.to_owned(), + &CancellationListener::new(None)); } #[test] @@ -1167,14 +1038,14 @@ fn test_load_sets_default_accept_encoding_to_gzip_and_deflate() { let http_state = HttpState::new(); let ui_provider = TestProvider::new(); - let _ = load::<AssertRequestMustIncludeHeaders, TestProvider>(load_data, - &ui_provider, &http_state, - None, - &AssertMustIncludeHeadersRequestFactory { - expected_headers: accept_encoding_headers, - body: <[_]>::to_vec("Yay!".as_bytes()) - }, DEFAULT_USER_AGENT.to_owned(), - &CancellationListener::new(None)); + let _ = load(load_data, + &ui_provider, &http_state, + None, + &AssertMustIncludeHeadersRequestFactory { + expected_headers: accept_encoding_headers, + body: <[_]>::to_vec("Yay!".as_bytes()) + }, DEFAULT_USER_AGENT.to_owned(), + &CancellationListener::new(None)); } #[test] @@ -1184,7 +1055,7 @@ fn test_load_errors_when_there_a_redirect_loop() { impl HttpRequestFactory for Factory { type R = MockRequest; - fn create(&self, url: Url, _: Method) -> Result<MockRequest, LoadError> { + fn create(&self, url: Url, _: Method, _: Headers) -> Result<MockRequest, LoadError> { if url.domain().unwrap() == "mozilla.com" { Ok(MockRequest::new(ResponseType::Redirect("http://mozilla.org".to_owned()))) } else if url.domain().unwrap() == "mozilla.org" { @@ -1201,8 +1072,8 @@ fn test_load_errors_when_there_a_redirect_loop() { let http_state = HttpState::new(); let ui_provider = TestProvider::new(); - match load::<MockRequest, TestProvider>(load_data, &ui_provider, &http_state, None, &Factory, - DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None)) { + match load(load_data, &ui_provider, &http_state, None, &Factory, + DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None)) { Err(LoadError::InvalidRedirect(_, msg)) => { assert_eq!(msg, "redirect loop"); }, @@ -1217,7 +1088,7 @@ fn test_load_errors_when_there_is_too_many_redirects() { impl HttpRequestFactory for Factory { type R = MockRequest; - fn create(&self, url: Url, _: Method) -> Result<MockRequest, LoadError> { + fn create(&self, url: Url, _: Method, _: Headers) -> Result<MockRequest, LoadError> { if url.domain().unwrap() == "mozilla.com" { Ok(MockRequest::new(ResponseType::Redirect(format!("{}/1", url.serialize())))) } else { @@ -1232,8 +1103,8 @@ fn test_load_errors_when_there_is_too_many_redirects() { let http_state = HttpState::new(); let ui_provider = TestProvider::new(); - match load::<MockRequest, TestProvider>(load_data, &ui_provider, &http_state, None, &Factory, - DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None)) { + match load(load_data, &ui_provider, &http_state, None, &Factory, + DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None)) { Err(LoadError::MaxRedirects(url)) => { assert_eq!(url.domain().unwrap(), "mozilla.com") }, @@ -1248,7 +1119,7 @@ fn test_load_follows_a_redirect() { impl HttpRequestFactory for Factory { type R = MockRequest; - fn create(&self, url: Url, _: Method) -> Result<MockRequest, LoadError> { + fn create(&self, url: Url, _: Method, _: Headers) -> Result<MockRequest, LoadError> { if url.domain().unwrap() == "mozilla.com" { Ok(MockRequest::new(ResponseType::Redirect("http://mozilla.org".to_owned()))) } else if url.domain().unwrap() == "mozilla.org" { @@ -1271,8 +1142,8 @@ fn test_load_follows_a_redirect() { let http_state = HttpState::new(); let ui_provider = TestProvider::new(); - match load::<MockRequest, TestProvider>(load_data, &ui_provider, &http_state, None, &Factory, - DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None)) { + match load(load_data, &ui_provider, &http_state, None, &Factory, + DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None)) { Err(e) => panic!("expected to follow a redirect {:?}", e), Ok(mut lr) => { let response = read_response(&mut lr); @@ -1286,7 +1157,7 @@ struct DontConnectFactory; impl HttpRequestFactory for DontConnectFactory { type R = MockRequest; - fn create(&self, url: Url, _: Method) -> Result<MockRequest, LoadError> { + fn create(&self, url: Url, _: Method, _: Headers) -> Result<MockRequest, LoadError> { Err(LoadError::Connection(url, "should not have connected".to_owned())) } } @@ -1299,12 +1170,12 @@ fn test_load_errors_when_scheme_is_not_http_or_https() { let http_state = HttpState::new(); let ui_provider = TestProvider::new(); - match load::<MockRequest, TestProvider>(load_data, - &ui_provider, &http_state, - None, - &DontConnectFactory, - DEFAULT_USER_AGENT.to_owned(), - &CancellationListener::new(None)) { + match load(load_data, + &ui_provider, &http_state, + None, + &DontConnectFactory, + DEFAULT_USER_AGENT.to_owned(), + &CancellationListener::new(None)) { Err(LoadError::UnsupportedScheme(_)) => {} _ => panic!("expected ftp scheme to be unsupported") } @@ -1318,12 +1189,12 @@ fn test_load_errors_when_viewing_source_and_inner_url_scheme_is_not_http_or_http let http_state = HttpState::new(); let ui_provider = TestProvider::new(); - match load::<MockRequest, TestProvider>(load_data, - &ui_provider, &http_state, - None, - &DontConnectFactory, - DEFAULT_USER_AGENT.to_owned(), - &CancellationListener::new(None)) { + match load(load_data, + &ui_provider, &http_state, + None, + &DontConnectFactory, + DEFAULT_USER_AGENT.to_owned(), + &CancellationListener::new(None)) { Err(LoadError::UnsupportedScheme(_)) => {} _ => panic!("expected ftp scheme to be unsupported") } @@ -1340,7 +1211,7 @@ fn test_load_errors_when_cancelled() { impl HttpRequestFactory for Factory { type R = MockRequest; - fn create(&self, _: Url, _: Method) -> Result<MockRequest, LoadError> { + fn create(&self, _: Url, _: Method, _: Headers) -> Result<MockRequest, LoadError> { let mut headers = Headers::new(); headers.set(Host { hostname: "Kaboom!".to_owned(), port: None }); Ok(MockRequest::new( @@ -1360,12 +1231,12 @@ fn test_load_errors_when_cancelled() { let http_state = HttpState::new(); let ui_provider = TestProvider::new(); - match load::<MockRequest, TestProvider>(load_data, - &ui_provider, &http_state, - None, - &Factory, - DEFAULT_USER_AGENT.to_owned(), - &cancel_listener) { + match load(load_data, + &ui_provider, &http_state, + None, + &Factory, + DEFAULT_USER_AGENT.to_owned(), + &cancel_listener) { Err(LoadError::Cancelled(_, _)) => (), _ => panic!("expected load cancelled error!") } @@ -1379,24 +1250,26 @@ fn test_redirect_from_x_to_y_provides_y_cookies_from_y() { struct Factory; impl HttpRequestFactory for Factory { - type R = AssertRequestMustIncludeHeaders; + type R = MockRequest; - fn create(&self, url: Url, _: Method) -> Result<AssertRequestMustIncludeHeaders, LoadError> { + fn create(&self, url: Url, _: Method, headers: Headers) -> Result<MockRequest, LoadError> { if url.domain().unwrap() == "mozilla.com" { let mut expected_headers_x = Headers::new(); expected_headers_x.set_raw("Cookie".to_owned(), vec![<[_]>::to_vec("mozillaIsNot=dotCom".as_bytes())]); + assert_headers_included(&expected_headers_x, &headers); - Ok(AssertRequestMustIncludeHeaders::new( - ResponseType::Redirect("http://mozilla.org".to_owned()), Some(expected_headers_x))) + Ok(MockRequest::new( + ResponseType::Redirect("http://mozilla.org".to_owned()))) } else if url.domain().unwrap() == "mozilla.org" { let mut expected_headers_y = Headers::new(); expected_headers_y.set_raw( "Cookie".to_owned(), vec![<[_]>::to_vec("mozillaIs=theBest".as_bytes())]); + assert_headers_included(&expected_headers_y, &headers); - Ok(AssertRequestMustIncludeHeaders::new( - ResponseType::Text(<[_]>::to_vec("Yay!".as_bytes())), Some(expected_headers_y))) + Ok(MockRequest::new( + ResponseType::Text(<[_]>::to_vec("Yay!".as_bytes())))) } else { panic!("unexpected host {:?}", url) } @@ -1428,12 +1301,12 @@ fn test_redirect_from_x_to_y_provides_y_cookies_from_y() { cookie_jar.push(cookie_y, CookieSource::HTTP); } - match load::<AssertRequestMustIncludeHeaders, TestProvider>(load_data, - &ui_provider, &http_state, - None, - &Factory, - DEFAULT_USER_AGENT.to_owned(), - &CancellationListener::new(None)) { + match load(load_data, + &ui_provider, &http_state, + None, + &Factory, + DEFAULT_USER_AGENT.to_owned(), + &CancellationListener::new(None)) { Err(e) => panic!("expected to follow a redirect {:?}", e), Ok(mut lr) => { let response = read_response(&mut lr); @@ -1449,22 +1322,20 @@ fn test_redirect_from_x_to_x_provides_x_with_cookie_from_first_response() { struct Factory; impl HttpRequestFactory for Factory { - type R = AssertRequestMustIncludeHeaders; + type R = MockRequest; - fn create(&self, url: Url, _: Method) -> Result<AssertRequestMustIncludeHeaders, LoadError> { + fn create(&self, url: Url, _: Method, headers: Headers) -> Result<MockRequest, LoadError> { if url.path().unwrap()[0] == "initial" { let mut initial_answer_headers = Headers::new(); initial_answer_headers.set_raw("set-cookie", vec![b"mozillaIs=theBest; path=/;".to_vec()]); - Ok(AssertRequestMustIncludeHeaders::new( + Ok(MockRequest::new( ResponseType::RedirectWithHeaders("http://mozilla.org/subsequent/".to_owned(), - initial_answer_headers), - None)) + initial_answer_headers))) } else if url.path().unwrap()[0] == "subsequent" { let mut expected_subsequent_headers = Headers::new(); expected_subsequent_headers.set_raw("Cookie", vec![b"mozillaIs=theBest".to_vec()]); - Ok(AssertRequestMustIncludeHeaders::new( - ResponseType::Text(b"Yay!".to_vec()), - Some(expected_subsequent_headers))) + assert_headers_included(&expected_subsequent_headers, &headers); + Ok(MockRequest::new(ResponseType::Text(b"Yay!".to_vec()))) } else { panic!("unexpected host {:?}", url) } @@ -1476,12 +1347,12 @@ fn test_redirect_from_x_to_x_provides_x_with_cookie_from_first_response() { let http_state = HttpState::new(); let ui_provider = TestProvider::new(); - match load::<AssertRequestMustIncludeHeaders, TestProvider>(load_data, - &ui_provider, &http_state, - None, - &Factory, - DEFAULT_USER_AGENT.to_owned(), - &CancellationListener::new(None)) { + match load(load_data, + &ui_provider, &http_state, + None, + &Factory, + DEFAULT_USER_AGENT.to_owned(), + &CancellationListener::new(None)) { Err(e) => panic!("expected to follow a redirect {:?}", e), Ok(mut lr) => { let response = read_response(&mut lr); @@ -1518,7 +1389,7 @@ fn test_if_auth_creds_not_in_url_but_in_cache_it_sets_it() { ) ); - let _ = load::<AssertRequestMustIncludeHeaders, TestProvider>( + let _ = load( load_data.clone(), &ui_provider, &http_state, None, &AssertMustIncludeHeadersRequestFactory { expected_headers: auth_header, @@ -1545,7 +1416,7 @@ fn test_auth_ui_sets_header_on_401() { let load_data = LoadData::new(LoadContext::Browsing, url, None); - match load::<AssertAuthHeaderRequest, TestProvider>( + match load( load_data.clone(), &ui_provider, &http_state, None, &AssertAuthHeaderRequestFactory { expected_headers: auth_header, |