From 26a6e058e7ddb17ccb553a806260879627d2247f Mon Sep 17 00:00:00 2001 From: Sam Gibson Date: Sat, 15 Aug 2015 15:04:23 +1000 Subject: [PATCH] Adds more tests for checking request headers --- components/net/http_loader.rs | 46 +++++++------ tests/unit/net/http_loader.rs | 122 +++++++++++++++++++++++++++++++--- 2 files changed, 139 insertions(+), 29 deletions(-) diff --git a/components/net/http_loader.rs b/components/net/http_loader.rs index 9cf6f15c4d2..7625393c582 100644 --- a/components/net/http_loader.rs +++ b/components/net/http_loader.rs @@ -274,6 +274,26 @@ pub enum LoadError { MaxRedirects(Url) } +#[inline(always)] +fn set_default_accept_encoding(headers: &mut Headers) { + if !headers.has::() { + headers.set_raw("Accept-Encoding".to_owned(), vec![b"gzip, deflate".to_vec()]); + } +} + +#[inline(always)] +fn set_default_accept(headers: &mut Headers) { + if !headers.has::() { + let accept = Accept(vec![ + qitem(Mime(TopLevel::Text, SubLevel::Html, vec![])), + qitem(Mime(TopLevel::Application, SubLevel::Ext("xhtml+xml".to_string()), vec![])), + QualityItem::new(Mime(TopLevel::Application, SubLevel::Xml, vec![]), Quality(900u16)), + QualityItem::new(Mime(TopLevel::Star, SubLevel::Star, vec![]), Quality(800u16)), + ]); + headers.set(accept); + } +} + pub fn load(mut load_data: LoadData, resource_mgr_chan: IpcSender, devtools_chan: Option>, @@ -321,9 +341,7 @@ pub fn load(mut load_data: LoadData, info!("requesting {}", url.serialize()); - // let mut req = try!(requester.build(url.clone(), load_data.method.clone())); - - //Ensure that the host header is set from the original url + // Ensure that the host header is set from the original url let host = Host { hostname: doc_url.serialize_host().unwrap(), port: doc_url.port_or_default() @@ -343,17 +361,8 @@ pub fn load(mut load_data: LoadData, request_headers.set(host); - - // --- Set default accept header - if !request_headers.has::() { - let accept = Accept(vec![ - qitem(Mime(TopLevel::Text, SubLevel::Html, vec![])), - qitem(Mime(TopLevel::Application, SubLevel::Ext("xhtml+xml".to_string()), vec![])), - QualityItem::new(Mime(TopLevel::Application, SubLevel::Xml, vec![]), Quality(900u16)), - QualityItem::new(Mime(TopLevel::Star, SubLevel::Star, vec![]), Quality(800u16)), - ]); - request_headers.set(accept); - } + set_default_accept(&mut request_headers); + set_default_accept_encoding(&mut request_headers); // --- Fetch cookies let (tx, rx) = ipc::channel().unwrap(); @@ -366,13 +375,7 @@ pub fn load(mut load_data: LoadData, request_headers.set_raw("Cookie".to_owned(), v); } - // --- Set default accept encoding - if !request_headers.has::() { - request_headers.set_raw("Accept-Encoding".to_owned(), vec![b"gzip, deflate".to_vec()]); - } - - // --- Start sending the request - // TODO: Avoid automatically sending request body if a redirect has occurred. + // --- Send the request let mut req = try!(request_factory.create(url.clone(), load_data.method.clone())); *req.headers_mut() = request_headers; @@ -384,6 +387,7 @@ pub fn load(mut load_data: LoadData, info!("{:?}", load_data.data); } + // TODO: Avoid automatically sending request body if a redirect has occurred. if let Some(ref data) = load_data.data { req.headers_mut().set(ContentLength(data.len() as u64)); } diff --git a/tests/unit/net/http_loader.rs b/tests/unit/net/http_loader.rs index 876aed61d81..e8f9a2a7b4a 100644 --- a/tests/unit/net/http_loader.rs +++ b/tests/unit/net/http_loader.rs @@ -100,23 +100,129 @@ impl MockRequest { } } +fn response_for_request_type(t: RequestType) -> Result { + match t { + RequestType::Redirect(location) => { + Ok(redirect_to(location)) + }, + RequestType::Text(b) => { + Ok(respond_with(b)) + } + } +} + impl HttpRequest for MockRequest { type R=MockResponse; fn headers_mut(&mut self) -> &mut Headers { &mut self.headers } fn send(self, _: &Option>) -> Result { - match self.t { - RequestType::Redirect(location) => { - Ok(redirect_to(location)) - }, - RequestType::Text(b) => { - Ok(respond_with(b)) - } - } + response_for_request_type(self.t) } } +struct AssertMustHaveHeadersRequest { + expected_headers: Headers, + request_headers: Headers, + t: RequestType +} + +impl AssertMustHaveHeadersRequest { + fn new(t: RequestType, expected_headers: Headers) -> Self { + AssertMustHaveHeadersRequest { expected_headers: expected_headers, request_headers: Headers::new(), t: t } + } +} + +impl HttpRequest for AssertMustHaveHeadersRequest { + type R=MockResponse; + + fn headers_mut(&mut self) -> &mut Headers { &mut self.request_headers } + + fn send(self, _: &Option>) -> Result { + 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) + } +} + +struct AssertMustHaveHeadersRequestFactory { + expected_headers: Headers, + body: Vec +} + +impl HttpRequestFactory for AssertMustHaveHeadersRequestFactory { + type R=AssertMustHaveHeadersRequest; + + fn create(&self, _: Url, _: Method) -> Result { + Ok( + AssertMustHaveHeadersRequest::new( + RequestType::Text(self.body.clone()), + self.expected_headers.clone() + ) + ) + } +} + +#[test] +fn test_load_sets_content_length_to_length_of_request_body() { + let content = "This is a request body"; + + let url = Url::parse("http://mozilla.com").unwrap(); + let resource_mgr = new_resource_task(None, None); + let mut load_data = LoadData::new(url.clone(), None); + load_data.data = Some(<[_]>::to_vec(content.as_bytes())); + + let mut content_len_headers= Headers::new(); + content_len_headers.set_raw("Content-Length".to_owned(), vec![<[_]>::to_vec(&*format!("{}", content.len()).as_bytes())]); + + let hsts_list = Arc::new(Mutex::new(HSTSList { entries: Vec::new() })); + + let _ = load::(load_data.clone(), resource_mgr, None, hsts_list, &AssertMustHaveHeadersRequestFactory { + expected_headers: content_len_headers, + body: <[_]>::to_vec(&*load_data.data.unwrap()) + }); +} + +#[test] +fn test_load_sets_default_accept_to_html_xhtml_xml_and_then_anything_else() { + let mut accept_headers = Headers::new(); + accept_headers.set_raw("Accept".to_owned(), vec![b"text/html, application/xhtml+xml, application/xml; q=0.9, */*; q=0.8".to_vec()]); + + let url = Url::parse("http://mozilla.com").unwrap(); + let resource_mgr = new_resource_task(None, None); + let mut load_data = LoadData::new(url.clone(), None); + load_data.data = Some(<[_]>::to_vec("Yay!".as_bytes())); + let hsts_list = Arc::new(Mutex::new(HSTSList { entries: Vec::new() })); + + let _ = load::(load_data, resource_mgr, None, hsts_list, &AssertMustHaveHeadersRequestFactory { + expected_headers: accept_headers, + body: <[_]>::to_vec("Yay!".as_bytes()) + }); +} + +#[test] +fn test_load_sets_default_accept_encoding_to_gzip_and_deflate() { + let mut accept_encoding_headers = Headers::new(); + accept_encoding_headers.set_raw("Accept-Encoding".to_owned(), vec![b"gzip, deflate".to_vec()]); + + let url = Url::parse("http://mozilla.com").unwrap(); + let resource_mgr = new_resource_task(None, None); + let mut load_data = LoadData::new(url.clone(), None); + load_data.data = Some(<[_]>::to_vec("Yay!".as_bytes())); + let hsts_list = Arc::new(Mutex::new(HSTSList { entries: Vec::new() })); + + let _ = load::(load_data, resource_mgr, None, hsts_list, &AssertMustHaveHeadersRequestFactory { + expected_headers: accept_encoding_headers, + body: <[_]>::to_vec("Yay!".as_bytes()) + }); +} + #[test] fn test_load_errors_when_there_a_redirect_loop() { struct Factory;