Kaynağa Gözat

Extract client creation to a single place

Jake Howard 4 yıl önce
ebeveyn
işleme
155109dea1
5 değiştirilmiş dosya ile 33 ekleme ve 23 silme
  1. 4 6
      src/api/admin.rs
  2. 2 5
      src/api/core/mod.rs
  3. 7 7
      src/api/core/two_factor/duo.rs
  4. 3 3
      src/api/icons.rs
  5. 17 2
      src/util.rs

+ 4 - 6
src/api/admin.rs

@@ -3,7 +3,7 @@ use serde::de::DeserializeOwned;
 use serde_json::Value;
 use std::{env, time::Duration};
 
-use reqwest::{blocking::Client, header::USER_AGENT};
+
 use rocket::{
     http::{Cookie, Cookies, SameSite},
     request::{self, FlashMessage, Form, FromRequest, Outcome, Request},
@@ -19,7 +19,7 @@ use crate::{
     db::{backup_database, get_sql_server_version, models::*, DbConn, DbConnType},
     error::{Error, MapResult},
     mail,
-    util::{format_naive_datetime_local, get_display_size, is_running_in_docker},
+    util::{format_naive_datetime_local, get_display_size, is_running_in_docker, get_reqwest_client},
     CONFIG,
 };
 
@@ -469,24 +469,22 @@ struct GitCommit {
 }
 
 fn get_github_api<T: DeserializeOwned>(url: &str) -> Result<T, Error> {
-    let github_api = Client::builder().build()?;
+    let github_api = get_reqwest_client();
 
     Ok(github_api
         .get(url)
         .timeout(Duration::from_secs(10))
-        .header(USER_AGENT, "Bitwarden_RS")
         .send()?
         .error_for_status()?
         .json::<T>()?)
 }
 
 fn has_http_access() -> bool {
-    let http_access = Client::builder().build().unwrap();
+    let http_access = get_reqwest_client();
 
     match http_access
         .head("https://github.com/dani-garcia/bitwarden_rs")
         .timeout(Duration::from_secs(10))
-        .header(USER_AGENT, "Bitwarden_RS")
         .send()
     {
         Ok(r) => r.status().is_success(),

+ 2 - 5
src/api/core/mod.rs

@@ -43,6 +43,7 @@ use crate::{
     auth::Headers,
     db::DbConn,
     error::Error,
+    util::get_reqwest_client,
 };
 
 #[put("/devices/identifier/<uuid>/clear-token")]
@@ -147,20 +148,16 @@ fn put_eq_domains(data: JsonUpcase<EquivDomainData>, headers: Headers, conn: DbC
 
 #[get("/hibp/breach?<username>")]
 fn hibp_breach(username: String) -> JsonResult {
-    let user_agent = "Bitwarden_RS";
     let url = format!(
         "https://haveibeenpwned.com/api/v3/breachedaccount/{}?truncateResponse=false&includeUnverified=false",
         username
     );
 
-    use reqwest::{blocking::Client, header::USER_AGENT};
-
     if let Some(api_key) = crate::CONFIG.hibp_api_key() {
-        let hibp_client = Client::builder().build()?;
+        let hibp_client = get_reqwest_client();
 
         let res = hibp_client
             .get(&url)
-            .header(USER_AGENT, user_agent)
             .header("hibp-api-key", api_key)
             .send()?;
 

+ 7 - 7
src/api/core/two_factor/duo.rs

@@ -12,6 +12,7 @@ use crate::{
         DbConn,
     },
     error::MapResult,
+    util::get_reqwest_client,
     CONFIG,
 };
 
@@ -185,9 +186,7 @@ fn activate_duo_put(data: JsonUpcase<EnableDuoData>, headers: Headers, conn: DbC
 }
 
 fn duo_api_request(method: &str, path: &str, params: &str, data: &DuoData) -> EmptyResult {
-    const AGENT: &str = "bitwarden_rs:Duo/1.0 (Rust)";
-
-    use reqwest::{blocking::Client, header::*, Method};
+    use reqwest::{header, Method};
     use std::str::FromStr;
 
     // https://duo.com/docs/authapi#api-details
@@ -199,11 +198,12 @@ fn duo_api_request(method: &str, path: &str, params: &str, data: &DuoData) -> Em
 
     let m = Method::from_str(method).unwrap_or_default();
 
-    Client::new()
-        .request(m, &url)
+    let client = get_reqwest_client();
+
+    client.request(m, &url)
         .basic_auth(username, Some(password))
-        .header(USER_AGENT, AGENT)
-        .header(DATE, date)
+        .header(header::USER_AGENT, "bitwarden_rs:Duo/1.0 (Rust)")
+        .header(header::DATE, date)
         .send()?
         .error_for_status()?;
 

+ 3 - 3
src/api/icons.rs

@@ -12,7 +12,7 @@ use regex::Regex;
 use reqwest::{blocking::Client, blocking::Response, header, Url};
 use rocket::{http::ContentType, http::Cookie, response::Content, Route};
 
-use crate::{error::Error, util::Cached, CONFIG};
+use crate::{error::Error, util::{Cached, get_reqwest_client_builder}, CONFIG};
 
 pub fn routes() -> Vec<Route> {
     routes![icon]
@@ -28,11 +28,11 @@ static CLIENT: Lazy<Client> = Lazy::new(|| {
     default_headers.insert(header::ACCEPT, header::HeaderValue::from_static("text/html,application/xhtml+xml,application/xml; q=0.9,image/webp,image/apng,*/*;q=0.8"));
 
     // Reuse the client between requests
-    Client::builder()
+    get_reqwest_client_builder()
         .timeout(Duration::from_secs(CONFIG.icon_download_timeout()))
         .default_headers(default_headers)
         .build()
-        .unwrap()
+        .expect("Failed to build icon client")
 });
 
 // Build Regex only once since this takes a lot of time.

+ 17 - 2
src/util.rs

@@ -478,7 +478,6 @@ pub fn retry<F, T, E>(func: F, max_tries: u32) -> Result<T, E>
 where
     F: Fn() -> Result<T, E>,
 {
-    use std::{thread::sleep, time::Duration};
     let mut tries = 0;
 
     loop {
@@ -497,12 +496,13 @@ where
     }
 }
 
+use std::{thread::sleep, time::Duration};
+
 pub fn retry_db<F, T, E>(func: F, max_tries: u32) -> Result<T, E>
 where
     F: Fn() -> Result<T, E>,
     E: std::error::Error,
 {
-    use std::{thread::sleep, time::Duration};
     let mut tries = 0;
 
     loop {
@@ -522,3 +522,18 @@ where
         }
     }
 }
+
+use reqwest::{blocking::{Client, ClientBuilder}, header};
+
+pub fn get_reqwest_client() -> Client {
+    get_reqwest_client_builder().build().expect("Failed to build client")
+}
+
+pub fn get_reqwest_client_builder() -> ClientBuilder {
+    let mut headers = header::HeaderMap::new();
+    headers.insert(header::USER_AGENT, header::HeaderValue::from_static("Bitwarden_RS"));
+    Client::builder()
+        .default_headers(headers)
+        .timeout(Duration::from_secs(10))
+
+}