* [pbs-devel] [PATCH proxmox-backup 1/2] HttpsConnector: add proxy authorization support
@ 2021-04-28 8:26 Dietmar Maurer
2021-04-28 8:26 ` [pbs-devel] [PATCH proxmox-backup 2/2] http: add helper to parse proxy configuration Dietmar Maurer
0 siblings, 1 reply; 2+ messages in thread
From: Dietmar Maurer @ 2021-04-28 8:26 UTC (permalink / raw)
To: pbs-devel
---
src/tools/http.rs | 49 +++++++++++++++++++++++++++++++++++------------
1 file changed, 37 insertions(+), 12 deletions(-)
diff --git a/src/tools/http.rs b/src/tools/http.rs
index 016d7673..e36e6c51 100644
--- a/src/tools/http.rs
+++ b/src/tools/http.rs
@@ -7,7 +7,7 @@ use std::sync::Arc;
use hyper::{Uri, Body};
use hyper::client::{Client, HttpConnector};
-use http::{Request, Response};
+use http::{Request, Response, HeaderValue};
use openssl::ssl::{SslConnector, SslMethod};
use futures::*;
use tokio::{
@@ -33,12 +33,14 @@ use crate::tools::{
pub struct ProxyConfig {
pub host: String,
pub port: u16,
+ pub authorization: Option<String>, // Proxy-Authorization header value
pub force_connect: bool,
}
/// Asyncrounous HTTP client implementation
pub struct SimpleHttp {
client: Client<HttpsConnector, Body>,
+ proxy_authorization: Option<String>, // Proxy-Authorization header value
}
impl SimpleHttp {
@@ -49,16 +51,39 @@ impl SimpleHttp {
}
pub fn with_ssl_connector(ssl_connector: SslConnector, proxy_config: Option<ProxyConfig>) -> 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 }
+ Self { client, proxy_authorization}
+ }
+
+ 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.proxy_authorization {
+ request
+ .headers_mut()
+ .insert(
+ http::header::PROXY_AUTHORIZATION,
+ HeaderValue::from_str(authorization)?,
+ );
+ }
+ }
+ Ok(())
}
- pub async fn request(&self, request: Request<Body>) -> Result<Response<Body>, Error> {
+ pub async fn request(&self, mut request: Request<Body>) -> Result<Response<Body>, Error> {
+ self.add_proxy_headers(&mut request)?;
self.client.request(request)
.map_err(Error::from)
.await
@@ -85,9 +110,7 @@ impl SimpleHttp {
.header(hyper::header::CONTENT_TYPE, content_type)
.body(body)?;
- self.client.request(request)
- .map_err(Error::from)
- .await
+ self.request(request).await
}
pub async fn get_string(
@@ -109,7 +132,7 @@ impl SimpleHttp {
let request = request.body(Body::empty())?;
- let res = self.client.request(request).await?;
+ let res = self.request(request).await?;
let status = res.status();
if !status.is_success() {
@@ -240,6 +263,8 @@ impl hyper::service::Service<Uri> for HttpsConnector {
Err(err) => return futures::future::err(err.into()).boxed(),
};
+ let authorization = proxy.authorization.clone();
+
if use_connect {
async move {
@@ -250,11 +275,11 @@ impl hyper::service::Service<Uri> for HttpsConnector {
let _ = set_tcp_keepalive(tcp_stream.as_raw_fd(), PROXMOX_BACKUP_TCP_KEEPALIVE_TIME);
- let connect_request = format!(
- "CONNECT {0}:{1} HTTP/1.1\r\n\
- Host: {0}:{1}\r\n\r\n",
- host, port,
- );
+ let mut connect_request = format!("CONNECT {0}:{1} HTTP/1.1\r\n", host, port);
+ if let Some(authorization) = authorization {
+ connect_request.push_str(&format!("Proxy-Authorization: {}\r\n", authorization));
+ }
+ connect_request.push_str(&format!("Host: {0}:{1}\r\n\r\n", host, port));
tcp_stream.write_all(connect_request.as_bytes()).await?;
tcp_stream.flush().await?;
--
2.20.1
^ permalink raw reply [flat|nested] 2+ messages in thread
* [pbs-devel] [PATCH proxmox-backup 2/2] http: add helper to parse proxy configuration
2021-04-28 8:26 [pbs-devel] [PATCH proxmox-backup 1/2] HttpsConnector: add proxy authorization support Dietmar Maurer
@ 2021-04-28 8:26 ` Dietmar Maurer
0 siblings, 0 replies; 2+ messages in thread
From: Dietmar Maurer @ 2021-04-28 8:26 UTC (permalink / raw)
To: pbs-devel
---
src/tools/http.rs | 62 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 62 insertions(+)
diff --git a/src/tools/http.rs b/src/tools/http.rs
index e36e6c51..f4ccefc9 100644
--- a/src/tools/http.rs
+++ b/src/tools/http.rs
@@ -37,6 +37,68 @@ pub struct ProxyConfig {
pub force_connect: bool,
}
+impl ProxyConfig {
+
+ /// Parse proxy config from ALL_PROXY environment var
+ pub fn from_proxy_env() -> Result<Option<ProxyConfig>, Error> {
+
+ // We only support/use ALL_PROXY environment
+
+ match std::env::var_os("ALL_PROXY") {
+ None => return Ok(None),
+ Some(all_proxy) => {
+ let all_proxy = match all_proxy.to_str() {
+ Some(s) => String::from(s),
+ None => bail!("non UTF-8 content in env ALL_PROXY"),
+ };
+ if all_proxy.is_empty() {
+ return Ok(None);
+ }
+ let config = Self::parse_proxy_url(&all_proxy)?;
+ Ok(Some(config))
+ }
+ }
+ }
+
+ /// Parse proxy configuration string [http://]<host>[:port]
+ ///
+ /// Default port is 1080 (like curl)
+ pub fn parse_proxy_url(http_proxy: &str) -> Result<ProxyConfig, Error> {
+ proxmox::try_block!({
+ let proxy_uri: Uri = http_proxy.parse()?;
+ let proxy_authority = match proxy_uri.authority() {
+ Some(authority) => authority,
+ None => bail!("missing proxy authority"),
+ };
+ let host = proxy_authority.host().to_owned();
+ let port = match proxy_uri.port() {
+ Some(port) => port.as_u16(),
+ None => 1080, // CURL default port
+ };
+
+ match proxy_uri.scheme_str() {
+ Some("http") => { /* Ok */ }
+ Some(scheme) => bail!("unsupported proxy scheme '{}'", scheme),
+ None => { /* assume HTTP */ }
+ }
+
+ let authority_vec: Vec<&str> = proxy_authority.as_str().rsplitn(2, '@').collect();
+ let authorization = if authority_vec.len() == 2 {
+ Some(format!("Basic {}", base64::encode(authority_vec[1])))
+ } else {
+ None
+ };
+
+ Ok(ProxyConfig {
+ host,
+ port,
+ authorization,
+ force_connect: false,
+ })
+ }).map_err(|err| format_err!("parse_proxy_url failed: {}", err))
+ }
+}
+
/// Asyncrounous HTTP client implementation
pub struct SimpleHttp {
client: Client<HttpsConnector, Body>,
--
2.20.1
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2021-04-28 8:26 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-04-28 8:26 [pbs-devel] [PATCH proxmox-backup 1/2] HttpsConnector: add proxy authorization support Dietmar Maurer
2021-04-28 8:26 ` [pbs-devel] [PATCH proxmox-backup 2/2] http: add helper to parse proxy configuration Dietmar Maurer
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox