diff options
Diffstat (limited to 'components/net')
-rw-r--r-- | components/net/http_loader.rs | 44 | ||||
-rw-r--r-- | components/net/resource_thread.rs | 8 |
2 files changed, 43 insertions, 9 deletions
diff --git a/components/net/http_loader.rs b/components/net/http_loader.rs index e0227a0637f..dec9e2fd2db 100644 --- a/components/net/http_loader.rs +++ b/components/net/http_loader.rs @@ -31,10 +31,10 @@ use net_traits::response::HttpsState; use net_traits::{CookieSource, IncludeSubdomains, LoadConsumer, LoadContext, LoadData, Metadata}; use openssl::ssl::error::{SslError, OpensslError}; use openssl::ssl::{SSL_OP_NO_SSLV2, SSL_OP_NO_SSLV3, SSL_VERIFY_PEER, SslContext, SslMethod}; -use resource_thread::{CancellationListener, send_error, start_sending_sniffed_opt}; +use resource_thread::{CancellationListener, send_error, start_sending_sniffed_opt, AuthCacheEntry}; use std::borrow::ToOwned; use std::boxed::FnBox; -use std::collections::HashSet; +use std::collections::{HashMap, HashSet}; use std::error::Error; use std::io::{self, Read, Write}; use std::sync::mpsc::Sender; @@ -80,6 +80,7 @@ pub fn create_http_connector() -> Arc<Pool<Connector>> { pub fn factory(user_agent: String, hsts_list: Arc<RwLock<HSTSList>>, cookie_jar: Arc<RwLock<CookieStorage>>, + auth_cache: Arc<RwLock<HashMap<Url, AuthCacheEntry>>>, devtools_chan: Option<Sender<DevtoolsControlMsg>>, connector: Arc<Pool<Connector>>) -> Box<FnBox(LoadData, @@ -94,6 +95,7 @@ pub fn factory(user_agent: String, connector, hsts_list, cookie_jar, + auth_cache, devtools_chan, cancel_listener, user_agent) @@ -130,6 +132,7 @@ fn load_for_consumer(load_data: LoadData, connector: Arc<Pool<Connector>>, hsts_list: Arc<RwLock<HSTSList>>, cookie_jar: Arc<RwLock<CookieStorage>>, + auth_cache: Arc<RwLock<HashMap<Url, AuthCacheEntry>>>, devtools_chan: Option<Sender<DevtoolsControlMsg>>, cancel_listener: CancellationListener, user_agent: String) { @@ -139,9 +142,9 @@ fn load_for_consumer(load_data: LoadData, }; let context = load_data.context.clone(); match load::<WrappedHttpRequest>(load_data, hsts_list, - cookie_jar, devtools_chan, - &factory, user_agent, - &cancel_listener) { + cookie_jar, auth_cache, + 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) @@ -516,6 +519,7 @@ pub fn modify_request_headers(headers: &mut Headers, url: &Url, user_agent: &str, cookie_jar: &Arc<RwLock<CookieStorage>>, + auth_cache: &Arc<RwLock<HashMap<Url, AuthCacheEntry>>>, load_data: &LoadData) { // Ensure that the host header is set from the original url let host = Host { @@ -536,19 +540,38 @@ pub fn modify_request_headers(headers: &mut Headers, set_default_accept(headers); set_default_accept_encoding(headers); + // https://fetch.spec.whatwg.org/#concept-http-network-or-cache-fetch step 11 if load_data.credentials_flag { set_request_cookies(url.clone(), headers, cookie_jar); // https://fetch.spec.whatwg.org/#http-network-or-cache-fetch step 12 - if !headers.has::<Authorization<Basic>>() { - if let Some(auth) = auth_from_url(url) { - headers.set(auth); + set_auth_header(headers, url, auth_cache); + } +} + +fn set_auth_header(headers: &mut Headers, + url: &Url, + auth_cache: &Arc<RwLock<HashMap<Url, AuthCacheEntry>>>) { + + if !headers.has::<Authorization<Basic>>() { + if let Some(auth) = auth_from_url(url) { + headers.set(auth); + } else { + if let Some(ref auth_entry) = auth_cache.read().unwrap().get(url) { + auth_from_entry(&auth_entry, headers); } } } } +fn auth_from_entry(auth_entry: &AuthCacheEntry, headers: &mut Headers) { + let user_name = auth_entry.user_name.clone(); + let password = Some(auth_entry.password.clone()); + + headers.set(Authorization(Basic { username: user_name, password: password })); +} + fn auth_from_url(doc_url: &Url) -> Option<Authorization<Basic>> { match doc_url.username() { Some(username) if username != "" => { @@ -665,6 +688,7 @@ pub fn obtain_response<A>(request_factory: &HttpRequestFactory<R=A>, pub fn load<A>(load_data: LoadData, hsts_list: Arc<RwLock<HSTSList>>, cookie_jar: Arc<RwLock<CookieStorage>>, + auth_cache: Arc<RwLock<HashMap<Url, AuthCacheEntry>>>, devtools_chan: Option<Sender<DevtoolsControlMsg>>, request_factory: &HttpRequestFactory<R=A>, user_agent: String, @@ -730,7 +754,9 @@ pub fn load<A>(load_data: LoadData, let request_id = uuid::Uuid::new_v4().to_simple_string(); - 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, + &auth_cache, &load_data); let response = try!(obtain_response(request_factory, &doc_url, &method, &request_headers, &cancel_listener, &load_data.data, &load_data.method, diff --git a/components/net/resource_thread.rs b/components/net/resource_thread.rs index 89e63e14f79..10530a40b2d 100644 --- a/components/net/resource_thread.rs +++ b/components/net/resource_thread.rs @@ -269,9 +269,15 @@ impl Drop for CancellationListener { } } +pub struct AuthCacheEntry { + pub user_name: String, + pub password: String, +} + pub struct ResourceManager { user_agent: String, cookie_storage: Arc<RwLock<CookieStorage>>, + auth_cache: Arc<RwLock<HashMap<Url, AuthCacheEntry>>>, mime_classifier: Arc<MIMEClassifier>, devtools_chan: Option<Sender<DevtoolsControlMsg>>, hsts_list: Arc<RwLock<HSTSList>>, @@ -287,6 +293,7 @@ impl ResourceManager { ResourceManager { user_agent: user_agent, cookie_storage: Arc::new(RwLock::new(CookieStorage::new())), + auth_cache: Arc::new(RwLock::new(HashMap::new())), mime_classifier: Arc::new(MIMEClassifier::new()), devtools_chan: devtools_channel, hsts_list: Arc::new(RwLock::new(hsts_list)), @@ -341,6 +348,7 @@ impl ResourceManager { http_loader::factory(self.user_agent.clone(), self.hsts_list.clone(), self.cookie_storage.clone(), + self.auth_cache.clone(), self.devtools_chan.clone(), self.connector.clone()), "data" => from_factory(data_loader::factory), |