diff --git a/src/acme/client.rs b/src/acme/client.rs index 28f277e9..1a6ca46f 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::SimpleHttp; +use crate::tools::{pbs_simple_http, SimpleHttp}; /// Our on-disk format inherited from PVE's proxmox-acme code. #[derive(Deserialize, Serialize)] @@ -72,7 +72,7 @@ impl AcmeClient { account: None, directory: None, nonce: None, - http_client: SimpleHttp::new(None), + http_client: pbs_simple_http(None), } } diff --git a/src/api2/node/apt.rs b/src/api2/node/apt.rs index 120d5339..9b2d1572 100644 --- a/src/api2/node/apt.rs +++ b/src/api2/node/apt.rs @@ -11,7 +11,11 @@ use proxmox_http::http::ProxyConfig; use crate::config::node; use crate::server::WorkerTask; -use crate::tools::{apt, SimpleHttp, subscription}; +use crate::tools::{ + apt, + pbs_simple_http, + subscription, +}; use crate::config::acl::{PRIV_SYS_AUDIT, PRIV_SYS_MODIFY}; use crate::api2::types::{Authid, APTUpdateInfo, NODE_SCHEMA, UPID_SCHEMA}; @@ -227,7 +231,7 @@ fn apt_get_changelog( } let proxy_config = read_and_update_proxy_config()?; - let mut client = SimpleHttp::new(proxy_config); + let mut client = pbs_simple_http(proxy_config); let changelog_url = &pkg_info[0].change_log_url; // FIXME: use 'apt-get changelog' for proxmox packages as well, once repo supports it diff --git a/src/tools.rs b/src/tools.rs index eb9a9fd0..4253c054 100644 --- a/src/tools.rs +++ b/src/tools.rs @@ -18,6 +18,8 @@ use percent_encoding::{utf8_percent_encode, AsciiSet}; pub use proxmox::tools::fd::Fd; use proxmox::tools::fs::{create_path, CreateOptions}; +use proxmox_http::http::ProxyConfig; + pub mod acl; pub mod apt; pub mod async_io; @@ -34,6 +36,7 @@ pub mod fuse_loop; mod simple_http_client; pub use simple_http_client::SimpleHttp; +pub use simple_http_client::SimpleHttpOptions; pub mod json; pub mod logrotate; @@ -483,6 +486,19 @@ impl AsAny for T { /// The default 2 hours are far too long for PBS pub const PROXMOX_BACKUP_TCP_KEEPALIVE_TIME: u32 = 120; +pub const DEFAULT_USER_AGENT_STRING: &'static str = "proxmox-backup-client/1.0"; + +/// Returns a new instance of `SimpleHttp` configured for PBS usage. +pub fn pbs_simple_http(proxy_config: Option) -> SimpleHttp { + let options = SimpleHttpOptions { + proxy_config, + user_agent: Some(DEFAULT_USER_AGENT_STRING.to_string()), + tcp_keepalive: Some(PROXMOX_BACKUP_TCP_KEEPALIVE_TIME), + ..Default::default() + }; + + SimpleHttp::with_options(options) +} /// This used to be: `SIMPLE_ENCODE_SET` plus space, `"`, `#`, `<`, `>`, backtick, `?`, `{`, `}` pub const DEFAULT_ENCODE_SET: &AsciiSet = &percent_encoding::CONTROLS // 0..1f and 7e diff --git a/src/tools/simple_http_client.rs b/src/tools/simple_http_client.rs index fa3eadf4..84e9b69f 100644 --- a/src/tools/simple_http_client.rs +++ b/src/tools/simple_http_client.rs @@ -12,50 +12,65 @@ use proxmox_http::http::{ client::HttpsConnector, }; -use crate::tools::PROXMOX_BACKUP_TCP_KEEPALIVE_TIME; +/// Options for a SimpleHttp client. +#[derive(Default)] +pub struct SimpleHttpOptions { + /// Proxy configuration + pub proxy_config: Option, + /// `User-Agent` header value, defaults to `proxmox-simple-http-client/0.1` + pub user_agent: Option, + /// TCP keepalive time, defaults to 7200 + pub tcp_keepalive: Option, +} + +impl SimpleHttpOptions { + fn get_proxy_authorization(&self) -> Option { + if let Some(ref proxy_config) = self.proxy_config { + if !proxy_config.force_connect { + return proxy_config.authorization.clone(); + } + } + + None + } +} /// Asyncrounous HTTP client implementation pub struct SimpleHttp { client: Client, - proxy_authorization: Option, // Proxy-Authorization header value - user_agent: Option, + options: SimpleHttpOptions, } impl SimpleHttp { + pub const DEFAULT_USER_AGENT_STRING: &'static str = "proxmox-simple-http-client/0.1"; - 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 new() -> Self { + Self::with_options(SimpleHttpOptions::default()) } - 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(); - } - } + pub fn with_options(options: SimpleHttpOptions) -> Self { + let ssl_connector = SslConnector::builder(SslMethod::tls()).unwrap().build(); + Self::with_ssl_connector(ssl_connector, options) + } + pub fn with_ssl_connector(ssl_connector: SslConnector, options: SimpleHttpOptions) -> Self { let connector = HttpConnector::new(); - let mut https = HttpsConnector::with_connector(connector, ssl_connector, PROXMOX_BACKUP_TCP_KEEPALIVE_TIME); - if let Some(proxy_config) = proxy_config { - https.set_proxy(proxy_config); + let mut https = HttpsConnector::with_connector(connector, ssl_connector, options.tcp_keepalive.unwrap_or(7200)); + if let Some(ref proxy_config) = options.proxy_config { + https.set_proxy(proxy_config.clone()); } let client = Client::builder().build(https); - Self { client, proxy_authorization, user_agent: None } + Self { client, options } } pub fn set_user_agent(&mut self, user_agent: &str) -> Result<(), Error> { - self.user_agent = Some(user_agent.to_owned()); + self.options.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 { + if let Some(ref authorization) = self.options.get_proxy_authorization() { request .headers_mut() .insert( @@ -68,7 +83,7 @@ impl SimpleHttp { } pub async fn request(&self, mut request: Request) -> Result, Error> { - let user_agent = if let Some(ref user_agent) = self.user_agent { + let user_agent = if let Some(ref user_agent) = self.options.user_agent { HeaderValue::from_str(&user_agent)? } else { HeaderValue::from_str(Self::DEFAULT_USER_AGENT_STRING)? diff --git a/src/tools/subscription.rs b/src/tools/subscription.rs index 212cf5e8..ed42e630 100644 --- a/src/tools/subscription.rs +++ b/src/tools/subscription.rs @@ -7,7 +7,11 @@ use regex::Regex; use proxmox::api::api; use crate::config::node; -use crate::tools::{self, SimpleHttp}; +use crate::tools::{ + self, + pbs_simple_http, + SimpleHttp, +}; use proxmox::tools::fs::{replace_file, CreateOptions}; /// How long the local key is valid for in between remote checks @@ -109,7 +113,7 @@ async fn register_subscription( None }; - let mut client = SimpleHttp::new(proxy_config); + let mut client = pbs_simple_http(proxy_config); let uri = "https://shop.maurer-it.com/modules/servers/licensing/verify.php"; let query = tools::json_object_to_query(params)?;