cleanup: split SimpleHttp client into extra file
This commit is contained in:
parent
b7b9a57425
commit
e5ef69ecf7
@ -19,7 +19,7 @@ use proxmox_acme_rs::{Account, Authorization, Challenge, Directory, Error, Error
|
|||||||
|
|
||||||
use crate::api2::types::AcmeAccountName;
|
use crate::api2::types::AcmeAccountName;
|
||||||
use crate::config::acme::account_path;
|
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.
|
/// Our on-disk format inherited from PVE's proxmox-acme code.
|
||||||
#[derive(Deserialize, Serialize)]
|
#[derive(Deserialize, Serialize)]
|
||||||
|
@ -7,7 +7,7 @@ use proxmox::api::{api, RpcEnvironment, RpcEnvironmentType, Permission};
|
|||||||
use proxmox::api::router::{Router, SubdirMap};
|
use proxmox::api::router::{Router, SubdirMap};
|
||||||
|
|
||||||
use crate::server::WorkerTask;
|
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::config::acl::{PRIV_SYS_AUDIT, PRIV_SYS_MODIFY};
|
||||||
use crate::api2::types::{Authid, APTUpdateInfo, NODE_SCHEMA, UPID_SCHEMA};
|
use crate::api2::types::{Authid, APTUpdateInfo, NODE_SCHEMA, UPID_SCHEMA};
|
||||||
|
@ -32,6 +32,10 @@ pub mod format;
|
|||||||
pub mod fs;
|
pub mod fs;
|
||||||
pub mod fuse_loop;
|
pub mod fuse_loop;
|
||||||
pub mod http;
|
pub mod http;
|
||||||
|
|
||||||
|
mod simple_http_client;
|
||||||
|
pub use simple_http_client::SimpleHttp;
|
||||||
|
|
||||||
pub mod json;
|
pub mod json;
|
||||||
pub mod logrotate;
|
pub mod logrotate;
|
||||||
pub mod loopdev;
|
pub mod loopdev;
|
||||||
|
@ -1,14 +1,12 @@
|
|||||||
use anyhow::{Error, format_err, bail};
|
use anyhow::{Error, format_err, bail};
|
||||||
use std::task::{Context, Poll};
|
use std::task::{Context, Poll};
|
||||||
use std::os::unix::io::AsRawFd;
|
use std::os::unix::io::AsRawFd;
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use hyper::Body;
|
use hyper::client::HttpConnector;
|
||||||
use hyper::client::{Client, HttpConnector};
|
use http::{Uri, uri::Authority};
|
||||||
use http::{Uri, uri::Authority, Request, Response, HeaderValue};
|
use openssl::ssl::SslConnector;
|
||||||
use openssl::ssl::{SslConnector, SslMethod};
|
|
||||||
use futures::*;
|
use futures::*;
|
||||||
use tokio::{
|
use tokio::{
|
||||||
io::{
|
io::{
|
||||||
@ -111,133 +109,6 @@ impl ProxyConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Asyncrounous HTTP client implementation
|
|
||||||
pub struct SimpleHttp {
|
|
||||||
client: Client<HttpsConnector, Body>,
|
|
||||||
proxy_authorization: Option<String>, // Proxy-Authorization header value
|
|
||||||
user_agent: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SimpleHttp {
|
|
||||||
|
|
||||||
pub const DEFAULT_USER_AGENT_STRING: &'static str = "proxmox-backup-client/1.0";
|
|
||||||
|
|
||||||
pub fn new(proxy_config: Option<ProxyConfig>) -> 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<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, 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<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, mut request: Request<Body>) -> Result<Response<Body>, 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<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))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct HttpsConnector {
|
pub struct HttpsConnector {
|
||||||
connector: HttpConnector,
|
connector: HttpConnector,
|
||||||
|
137
src/tools/simple_http_client.rs
Normal file
137
src/tools/simple_http_client.rs
Normal file
@ -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<HttpsConnector, Body>,
|
||||||
|
proxy_authorization: Option<String>, // Proxy-Authorization header value
|
||||||
|
user_agent: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SimpleHttp {
|
||||||
|
|
||||||
|
pub const DEFAULT_USER_AGENT_STRING: &'static str = "proxmox-backup-client/1.0";
|
||||||
|
|
||||||
|
pub fn new(proxy_config: Option<ProxyConfig>) -> 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<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, 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<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, mut request: Request<Body>) -> Result<Response<Body>, 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<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))
|
||||||
|
}
|
||||||
|
}
|
@ -6,7 +6,7 @@ use regex::Regex;
|
|||||||
|
|
||||||
use proxmox::api::api;
|
use proxmox::api::api;
|
||||||
|
|
||||||
use crate::tools::{self, http::SimpleHttp};
|
use crate::tools::{self, SimpleHttp};
|
||||||
use proxmox::tools::fs::{replace_file, CreateOptions};
|
use proxmox::tools::fs::{replace_file, CreateOptions};
|
||||||
|
|
||||||
/// How long the local key is valid for in between remote checks
|
/// How long the local key is valid for in between remote checks
|
||||||
|
Loading…
Reference in New Issue
Block a user