From e5ef69ecf70999c2811bf73f437c2ba9458df617 Mon Sep 17 00:00:00 2001 From: Dietmar Maurer Date: Thu, 6 May 2021 10:20:53 +0200 Subject: [PATCH] cleanup: split SimpleHttp client into extra file --- src/acme/client.rs | 2 +- src/api2/node/apt.rs | 2 +- src/tools.rs | 4 + src/tools/http.rs | 135 +------------------------------ src/tools/simple_http_client.rs | 137 ++++++++++++++++++++++++++++++++ src/tools/subscription.rs | 2 +- 6 files changed, 147 insertions(+), 135 deletions(-) create mode 100644 src/tools/simple_http_client.rs diff --git a/src/acme/client.rs b/src/acme/client.rs index e43a41b9..7fe30740 100644 --- a/src/acme/client.rs +++ b/src/acme/client.rs @@ -19,7 +19,7 @@ use proxmox_acme_rs::{Account, Authorization, Challenge, Directory, Error, Error use crate::api2::types::AcmeAccountName; use crate::config::acme::account_path; -use crate::tools::http::SimpleHttp; +use crate::tools::SimpleHttp; /// Our on-disk format inherited from PVE's proxmox-acme code. #[derive(Deserialize, Serialize)] diff --git a/src/api2/node/apt.rs b/src/api2/node/apt.rs index 44b13edd..cc9364cb 100644 --- a/src/api2/node/apt.rs +++ b/src/api2/node/apt.rs @@ -7,7 +7,7 @@ use proxmox::api::{api, RpcEnvironment, RpcEnvironmentType, Permission}; use proxmox::api::router::{Router, SubdirMap}; use crate::server::WorkerTask; -use crate::tools::{apt, http::SimpleHttp, subscription}; +use crate::tools::{apt, SimpleHttp, subscription}; use crate::config::acl::{PRIV_SYS_AUDIT, PRIV_SYS_MODIFY}; use crate::api2::types::{Authid, APTUpdateInfo, NODE_SCHEMA, UPID_SCHEMA}; diff --git a/src/tools.rs b/src/tools.rs index c58569a6..8f2acded 100644 --- a/src/tools.rs +++ b/src/tools.rs @@ -32,6 +32,10 @@ pub mod format; pub mod fs; pub mod fuse_loop; pub mod http; + +mod simple_http_client; +pub use simple_http_client::SimpleHttp; + pub mod json; pub mod logrotate; pub mod loopdev; diff --git a/src/tools/http.rs b/src/tools/http.rs index cfdd9b16..7eb7dce7 100644 --- a/src/tools/http.rs +++ b/src/tools/http.rs @@ -1,14 +1,12 @@ use anyhow::{Error, format_err, bail}; use std::task::{Context, Poll}; use std::os::unix::io::AsRawFd; -use std::collections::HashMap; use std::pin::Pin; use std::sync::Arc; -use hyper::Body; -use hyper::client::{Client, HttpConnector}; -use http::{Uri, uri::Authority, Request, Response, HeaderValue}; -use openssl::ssl::{SslConnector, SslMethod}; +use hyper::client::HttpConnector; +use http::{Uri, uri::Authority}; +use openssl::ssl::SslConnector; use futures::*; use tokio::{ io::{ @@ -111,133 +109,6 @@ impl ProxyConfig { } } -/// Asyncrounous HTTP client implementation -pub struct SimpleHttp { - client: Client, - proxy_authorization: Option, // Proxy-Authorization header value - user_agent: Option, -} - -impl SimpleHttp { - - pub const DEFAULT_USER_AGENT_STRING: &'static str = "proxmox-backup-client/1.0"; - - pub fn new(proxy_config: Option) -> Self { - let ssl_connector = SslConnector::builder(SslMethod::tls()).unwrap().build(); - Self::with_ssl_connector(ssl_connector, proxy_config) - } - - pub fn with_ssl_connector(ssl_connector: SslConnector, proxy_config: Option) -> Self { - - let mut proxy_authorization = None; - if let Some(ref proxy_config) = proxy_config { - if !proxy_config.force_connect { - proxy_authorization = proxy_config.authorization.clone(); - } - } - - let connector = HttpConnector::new(); - let mut https = HttpsConnector::with_connector(connector, ssl_connector); - if let Some(proxy_config) = proxy_config { - https.set_proxy(proxy_config); - } - let client = Client::builder().build(https); - Self { client, proxy_authorization, user_agent: None } - } - - pub fn set_user_agent(&mut self, user_agent: &str) -> Result<(), Error> { - self.user_agent = Some(user_agent.to_owned()); - Ok(()) - } - - fn add_proxy_headers(&self, request: &mut Request) -> Result<(), Error> { - if request.uri().scheme() != Some(&http::uri::Scheme::HTTPS) { - if let Some(ref authorization) = self.proxy_authorization { - request - .headers_mut() - .insert( - http::header::PROXY_AUTHORIZATION, - HeaderValue::from_str(authorization)?, - ); - } - } - Ok(()) - } - - pub async fn request(&self, mut request: Request) -> Result, Error> { - let user_agent = if let Some(ref user_agent) = self.user_agent { - HeaderValue::from_str(&user_agent)? - } else { - HeaderValue::from_str(Self::DEFAULT_USER_AGENT_STRING)? - }; - - request.headers_mut().insert(hyper::header::USER_AGENT, user_agent); - - self.add_proxy_headers(&mut request)?; - - self.client.request(request) - .map_err(Error::from) - .await - } - - pub async fn post( - &mut self, - uri: &str, - body: Option, - content_type: Option<&str>, - ) -> Result, Error> { - - let body = if let Some(body) = body { - Body::from(body) - } else { - Body::empty() - }; - let content_type = content_type.unwrap_or("application/json"); - - let request = Request::builder() - .method("POST") - .uri(uri) - .header(hyper::header::CONTENT_TYPE, content_type) - .body(body)?; - - self.request(request).await - } - - pub async fn get_string( - &mut self, - uri: &str, - extra_headers: Option<&HashMap>, - ) -> Result { - - let mut request = Request::builder() - .method("GET") - .uri(uri); - - if let Some(hs) = extra_headers { - for (h, v) in hs.iter() { - request = request.header(h, v); - } - } - - let request = request.body(Body::empty())?; - - let res = self.request(request).await?; - - let status = res.status(); - if !status.is_success() { - bail!("Got bad status '{}' from server", status) - } - - Self::response_body_string(res).await - } - - pub async fn response_body_string(res: Response) -> Result { - let buf = hyper::body::to_bytes(res).await?; - String::from_utf8(buf.to_vec()) - .map_err(|err| format_err!("Error converting HTTP result data: {}", err)) - } -} - #[derive(Clone)] pub struct HttpsConnector { connector: HttpConnector, diff --git a/src/tools/simple_http_client.rs b/src/tools/simple_http_client.rs new file mode 100644 index 00000000..ca11ded8 --- /dev/null +++ b/src/tools/simple_http_client.rs @@ -0,0 +1,137 @@ +use anyhow::{Error, format_err, bail}; +use std::collections::HashMap; + +use hyper::Body; +use hyper::client::{Client, HttpConnector}; +use http::{Request, Response, HeaderValue}; +use openssl::ssl::{SslConnector, SslMethod}; +use futures::*; + +use crate::tools::http::{HttpsConnector, ProxyConfig}; + +/// Asyncrounous HTTP client implementation +pub struct SimpleHttp { + client: Client, + proxy_authorization: Option, // Proxy-Authorization header value + user_agent: Option, +} + +impl SimpleHttp { + + pub const DEFAULT_USER_AGENT_STRING: &'static str = "proxmox-backup-client/1.0"; + + pub fn new(proxy_config: Option) -> Self { + let ssl_connector = SslConnector::builder(SslMethod::tls()).unwrap().build(); + Self::with_ssl_connector(ssl_connector, proxy_config) + } + + pub fn with_ssl_connector(ssl_connector: SslConnector, proxy_config: Option) -> Self { + + let mut proxy_authorization = None; + if let Some(ref proxy_config) = proxy_config { + if !proxy_config.force_connect { + proxy_authorization = proxy_config.authorization.clone(); + } + } + + let connector = HttpConnector::new(); + let mut https = HttpsConnector::with_connector(connector, ssl_connector); + if let Some(proxy_config) = proxy_config { + https.set_proxy(proxy_config); + } + let client = Client::builder().build(https); + Self { client, proxy_authorization, user_agent: None } + } + + pub fn set_user_agent(&mut self, user_agent: &str) -> Result<(), Error> { + self.user_agent = Some(user_agent.to_owned()); + Ok(()) + } + + fn add_proxy_headers(&self, request: &mut Request) -> Result<(), Error> { + if request.uri().scheme() != Some(&http::uri::Scheme::HTTPS) { + if let Some(ref authorization) = self.proxy_authorization { + request + .headers_mut() + .insert( + http::header::PROXY_AUTHORIZATION, + HeaderValue::from_str(authorization)?, + ); + } + } + Ok(()) + } + + pub async fn request(&self, mut request: Request) -> Result, Error> { + let user_agent = if let Some(ref user_agent) = self.user_agent { + HeaderValue::from_str(&user_agent)? + } else { + HeaderValue::from_str(Self::DEFAULT_USER_AGENT_STRING)? + }; + + request.headers_mut().insert(hyper::header::USER_AGENT, user_agent); + + self.add_proxy_headers(&mut request)?; + + self.client.request(request) + .map_err(Error::from) + .await + } + + pub async fn post( + &mut self, + uri: &str, + body: Option, + content_type: Option<&str>, + ) -> Result, Error> { + + let body = if let Some(body) = body { + Body::from(body) + } else { + Body::empty() + }; + let content_type = content_type.unwrap_or("application/json"); + + let request = Request::builder() + .method("POST") + .uri(uri) + .header(hyper::header::CONTENT_TYPE, content_type) + .body(body)?; + + self.request(request).await + } + + pub async fn get_string( + &mut self, + uri: &str, + extra_headers: Option<&HashMap>, + ) -> Result { + + let mut request = Request::builder() + .method("GET") + .uri(uri); + + if let Some(hs) = extra_headers { + for (h, v) in hs.iter() { + request = request.header(h, v); + } + } + + let request = request.body(Body::empty())?; + + let res = self.request(request).await?; + + let status = res.status(); + if !status.is_success() { + bail!("Got bad status '{}' from server", status) + } + + Self::response_body_string(res).await + } + + pub async fn response_body_string(res: Response) -> Result { + let buf = hyper::body::to_bytes(res).await?; + String::from_utf8(buf.to_vec()) + .map_err(|err| format_err!("Error converting HTTP result data: {}", err)) + } +} diff --git a/src/tools/subscription.rs b/src/tools/subscription.rs index eaaf0389..29a2b13c 100644 --- a/src/tools/subscription.rs +++ b/src/tools/subscription.rs @@ -6,7 +6,7 @@ use regex::Regex; use proxmox::api::api; -use crate::tools::{self, http::SimpleHttp}; +use crate::tools::{self, SimpleHttp}; use proxmox::tools::fs::{replace_file, CreateOptions}; /// How long the local key is valid for in between remote checks