[pbs-devel] [RFC proxmox-backup 3/5] new http client implementation SimpleHttp (avoid static HTTP_CLIENT)
Dietmar Maurer
dietmar at proxmox.com
Wed Apr 21 13:17:00 CEST 2021
This one will have proxy support.
---
src/api2/node/apt.rs | 8 ++-
src/tools/http.rs | 122 +++++++++++++++++++++-----------------
src/tools/subscription.rs | 10 ++--
3 files changed, 80 insertions(+), 60 deletions(-)
diff --git a/src/api2/node/apt.rs b/src/api2/node/apt.rs
index e77b89fa..dbdb2019 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, subscription};
+use crate::tools::{apt, http::SimpleHttp, subscription};
use crate::config::acl::{PRIV_SYS_AUDIT, PRIV_SYS_MODIFY};
use crate::api2::types::{Authid, APTUpdateInfo, NODE_SCHEMA, UPID_SCHEMA};
@@ -194,10 +194,12 @@ fn apt_get_changelog(
bail!("Package '{}' not found", name);
}
+ let mut client = SimpleHttp::new();
+
let changelog_url = &pkg_info[0].change_log_url;
// FIXME: use 'apt-get changelog' for proxmox packages as well, once repo supports it
if changelog_url.starts_with("http://download.proxmox.com/") {
- let changelog = crate::tools::runtime::block_on(http::get_string(changelog_url, None))
+ let changelog = crate::tools::runtime::block_on(client.get_string(changelog_url, None))
.map_err(|err| format_err!("Error downloading changelog from '{}': {}", changelog_url, err))?;
Ok(json!(changelog))
@@ -221,7 +223,7 @@ fn apt_get_changelog(
auth_header.insert("Authorization".to_owned(),
format!("Basic {}", base64::encode(format!("{}:{}", key, id))));
- let changelog = crate::tools::runtime::block_on(http::get_string(changelog_url, Some(&auth_header)))
+ let changelog = crate::tools::runtime::block_on(client.get_string(changelog_url, Some(&auth_header)))
.map_err(|err| format_err!("Error downloading changelog from '{}': {}", changelog_url, err))?;
Ok(json!(changelog))
diff --git a/src/tools/http.rs b/src/tools/http.rs
index 3cd3af4e..f19d6527 100644
--- a/src/tools/http.rs
+++ b/src/tools/http.rs
@@ -1,5 +1,4 @@
use anyhow::{Error, format_err, bail};
-use lazy_static::lazy_static;
use std::task::{Context, Poll};
use std::os::unix::io::AsRawFd;
use std::collections::HashMap;
@@ -21,68 +20,85 @@ use crate::tools::{
},
};
-lazy_static! {
- static ref HTTP_CLIENT: Client<HttpsConnector, Body> = {
- let connector = SslConnector::builder(SslMethod::tls()).unwrap().build();
- let httpc = HttpConnector::new();
- let https = HttpsConnector::with_connector(httpc, connector);
- Client::builder().build(https)
- };
+/// Asyncrounous HTTP client implementation
+pub struct SimpleHttp {
+ client: Client<HttpsConnector, Body>,
}
-pub async fn get_string(uri: &str, extra_headers: Option<&HashMap<String, String>>) -> Result<String, Error> {
- let mut request = Request::builder()
- .method("GET")
- .uri(uri)
- .header("User-Agent", "proxmox-backup-client/1.0");
+impl SimpleHttp {
- if let Some(hs) = extra_headers {
- for (h, v) in hs.iter() {
- request = request.header(h, v);
- }
+ pub fn new() -> Self {
+ let ssl_connector = SslConnector::builder(SslMethod::tls()).unwrap().build();
+ Self::with_ssl_connector(ssl_connector)
}
- let request = request.body(Body::empty())?;
-
- let res = HTTP_CLIENT.request(request).await?;
+ pub fn with_ssl_connector(ssl_connector: SslConnector) -> Self {
+ let connector = HttpConnector::new();
+ let https = HttpsConnector::with_connector(connector, ssl_connector);
+ let client = Client::builder().build(https);
+ Self { client }
+ }
- let status = res.status();
- if !status.is_success() {
- bail!("Got bad status '{}' from server", status)
+ pub async fn post(
+ &mut self,
+ uri: &str,
+ body: Option<String>,
+ content_type: Option<&str>,
+ ) -> Result<Response<Body>, 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("User-Agent", "proxmox-backup-client/1.0")
+ .header(hyper::header::CONTENT_TYPE, content_type)
+ .body(body)?;
+
+ self.client.request(request)
+ .map_err(Error::from)
+ .await
}
- response_body_string(res).await
-}
+ pub async fn get_string(
+ &mut self,
+ uri: &str,
+ extra_headers: Option<&HashMap<String, String>>,
+ ) -> Result<String, Error> {
-pub async fn response_body_string(res: Response<Body>) -> Result<String, Error> {
- 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))
-}
+ let mut request = Request::builder()
+ .method("GET")
+ .uri(uri)
+ .header("User-Agent", "proxmox-backup-client/1.0");
+
+ if let Some(hs) = extra_headers {
+ for (h, v) in hs.iter() {
+ request = request.header(h, v);
+ }
+ }
-pub async fn post(
- uri: &str,
- body: Option<String>,
- content_type: Option<&str>,
-) -> Result<Response<Body>, 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("User-Agent", "proxmox-backup-client/1.0")
- .header(hyper::header::CONTENT_TYPE, content_type)
- .body(body)?;
-
-
- HTTP_CLIENT.request(request)
- .map_err(Error::from)
- .await
+ let request = request.body(Body::empty())?;
+
+ let res = self.client.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<Body>) -> Result<String, Error> {
+ 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)]
diff --git a/src/tools/subscription.rs b/src/tools/subscription.rs
index 9b9534ac..9a920aee 100644
--- a/src/tools/subscription.rs
+++ b/src/tools/subscription.rs
@@ -6,8 +6,7 @@ use regex::Regex;
use proxmox::api::api;
-use crate::tools;
-use crate::tools::http;
+use crate::tools::{self, http::SimpleHttp};
use proxmox::tools::fs::{replace_file, CreateOptions};
/// How long the local key is valid for in between remote checks
@@ -102,10 +101,13 @@ async fn register_subscription(
"ip": "localhost",
"check_token": challenge,
});
+
+ let mut client = SimpleHttp::new();
+
let uri = "https://shop.maurer-it.com/modules/servers/licensing/verify.php";
let query = tools::json_object_to_query(params)?;
- let response = http::post(uri, Some(query), Some("application/x-www-form-urlencoded")).await?;
- let body = http::response_body_string(response).await?;
+ let response = client.post(uri, Some(query), Some("application/x-www-form-urlencoded")).await?;
+ let body = SimpleHttp::response_body_string(response).await?;
Ok((body, challenge))
}
--
2.20.1
More information about the pbs-devel
mailing list