From: "Fabian Grünbichler" <f.gruenbichler@proxmox.com>
To: pbs-devel@lists.proxmox.com
Subject: [pbs-devel] [PATCH proxmox 10/13] http: takeover simple HTTP client from proxmox_backup
Date: Fri, 14 May 2021 15:44:46 +0200 [thread overview]
Message-ID: <20210514134457.1447930-11-f.gruenbichler@proxmox.com> (raw)
In-Reply-To: <20210514134457.1447930-1-f.gruenbichler@proxmox.com>
adapted to use already moved helpers/code.
Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
---
proxmox-http/src/http/client.rs | 4 +
proxmox-http/src/http/client/simple.rs | 157 +++++++++++++++++++++++++
2 files changed, 161 insertions(+)
create mode 100644 proxmox-http/src/http/client/simple.rs
diff --git a/proxmox-http/src/http/client.rs b/proxmox-http/src/http/client.rs
index 21a65e3..c55cbd4 100644
--- a/proxmox-http/src/http/client.rs
+++ b/proxmox-http/src/http/client.rs
@@ -1,3 +1,7 @@
mod connector;
pub use connector::HttpsConnector;
+
+mod simple;
+pub use simple::SimpleHttp;
+pub use simple::SimpleHttpOptions;
diff --git a/proxmox-http/src/http/client/simple.rs b/proxmox-http/src/http/client/simple.rs
new file mode 100644
index 0000000..110fa55
--- /dev/null
+++ b/proxmox-http/src/http/client/simple.rs
@@ -0,0 +1,157 @@
+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::http::{
+ ProxyConfig,
+ client::HttpsConnector,
+};
+
+/// Options for a SimpleHttp client.
+#[derive(Default)]
+pub struct SimpleHttpOptions {
+ /// Proxy configuration
+ pub proxy_config: Option<ProxyConfig>,
+ /// `User-Agent` header value, defaults to `proxmox-simple-http-client/0.1`
+ pub user_agent: Option<String>,
+ /// TCP keepalive time, defaults to 7200
+ pub tcp_keepalive: Option<u32>,
+}
+
+impl SimpleHttpOptions {
+ fn get_proxy_authorization(&self) -> Option<String> {
+ 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<HttpsConnector, Body>,
+ options: SimpleHttpOptions,
+}
+
+impl SimpleHttp {
+ pub const DEFAULT_USER_AGENT_STRING: &'static str = "proxmox-simple-http-client/0.1";
+
+ pub fn new() -> Self {
+ Self::with_options(SimpleHttpOptions::default())
+ }
+
+ 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, 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, options }
+ }
+
+ pub fn set_user_agent(&mut self, user_agent: &str) -> Result<(), Error> {
+ self.options.user_agent = Some(user_agent.to_owned());
+ Ok(())
+ }
+
+ fn add_proxy_headers(&self, request: &mut Request<Body>) -> Result<(), Error> {
+ if request.uri().scheme() != Some(&http::uri::Scheme::HTTPS) {
+ if let Some(ref authorization) = self.options.get_proxy_authorization() {
+ request
+ .headers_mut()
+ .insert(
+ http::header::PROXY_AUTHORIZATION,
+ HeaderValue::from_str(authorization)?,
+ );
+ }
+ }
+ Ok(())
+ }
+
+ pub async fn request(&self, mut request: Request<Body>) -> Result<Response<Body>, Error> {
+ 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)?
+ };
+
+ 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<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(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<String, String>>,
+ ) -> Result<String, Error> {
+
+ 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<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))
+ }
+}
--
2.20.1
next prev parent reply other threads:[~2021-05-14 13:45 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-05-14 13:44 [pbs-devel] [PATCH proxmox(-backup) 00/21] pull HTTP code into proxmox/proxmox-http Fabian Grünbichler
2021-05-14 13:44 ` [pbs-devel] [PATCH proxmox 01/13] proxmox: add missing +router -> futures dep Fabian Grünbichler
2021-05-17 8:22 ` [pbs-devel] applied: " Dietmar Maurer
2021-05-14 13:44 ` [pbs-devel] [PATCH proxmox 02/13] meta: add empty proxmox-http sub-crate Fabian Grünbichler
2021-05-14 13:44 ` [pbs-devel] [PATCH proxmox 03/13] http: takeover websocket feature from proxmox Fabian Grünbichler
2021-05-14 13:44 ` [pbs-devel] [PATCH proxmox 04/13] http: make clippy happy Fabian Grünbichler
2021-05-14 13:44 ` [pbs-devel] [PATCH proxmox 05/13] proxmox: takeover socket helper from proxmox_backup Fabian Grünbichler
2021-05-14 13:44 ` [pbs-devel] [PATCH proxmox 06/13] http: takeover MaybeTlsStream " Fabian Grünbichler
2021-05-14 13:44 ` [pbs-devel] [PATCH proxmox 07/13] http: takeover build_authority helper " Fabian Grünbichler
2021-05-14 13:44 ` [pbs-devel] [PATCH proxmox 08/13] http: takeover ProxyConfig " Fabian Grünbichler
2021-05-14 13:44 ` [pbs-devel] [PATCH proxmox 09/13] http: takeover tools::http " Fabian Grünbichler
2021-05-14 13:44 ` Fabian Grünbichler [this message]
2021-05-14 13:44 ` [pbs-devel] [PATCH proxmox 11/13] http: make clippy happy Fabian Grünbichler
2021-05-14 13:44 ` [pbs-devel] [PATCH proxmox 12/13] http: rustfmt Fabian Grünbichler
2021-05-14 13:44 ` [pbs-devel] [PATCH proxmox 13/13] http: update d/control Fabian Grünbichler
2021-05-14 13:44 ` [pbs-devel] [PATCH proxmox-backup 1/8] move websocket to new 'proxmox_http' crate Fabian Grünbichler
2021-05-17 8:35 ` [pbs-devel] applied: " Dietmar Maurer
2021-05-14 13:44 ` [pbs-devel] [PATCH proxmox-backup 2/8] refactor: move socket helper to proxmox crate Fabian Grünbichler
2021-05-14 13:44 ` [pbs-devel] [PATCH proxmox-backup 3/8] move MaybeTlsStream wrapper to proxmox_http Fabian Grünbichler
2021-05-14 13:44 ` [pbs-devel] [PATCH proxmox-backup 4/8] HttpsConnector: make keepalive configurable Fabian Grünbichler
2021-05-14 13:44 ` [pbs-devel] [PATCH proxmox-backup 5/8] move ProxyConfig to proxmox_http Fabian Grünbichler
2021-05-14 13:44 ` [pbs-devel] [PATCH proxmox-backup 6/8] move tools::http " Fabian Grünbichler
2021-05-14 13:44 ` [pbs-devel] [PATCH proxmox-backup 7/8] SimpleHttp: factor out product-specific bits Fabian Grünbichler
2021-05-14 13:44 ` [pbs-devel] [PATCH proxmox-backup 8/8] move SimpleHttp to proxmox_http Fabian Grünbichler
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210514134457.1447930-11-f.gruenbichler@proxmox.com \
--to=f.gruenbichler@proxmox.com \
--cc=pbs-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.