diff --git a/src/client/http_client.rs b/src/client/http_client.rs
index 62aa9571..a43ff3e9 100644
--- a/src/client/http_client.rs
+++ b/src/client/http_client.rs
@@ -127,9 +127,7 @@ impl HttpClient {
bail!("no password input mechanism available");
}
- fn run_request(
- request: Request
,
- ) -> Result {
+ fn build_client() -> Result>, Error> {
let mut builder = native_tls::TlsConnector::builder();
// FIXME: We need a CLI option for this!
builder.danger_accept_invalid_certs(true);
@@ -139,6 +137,13 @@ impl HttpClient {
let mut https = hyper_tls::HttpsConnector::from((httpc, tlsconnector));
https.https_only(true); // force it!
let client = Client::builder().build::<_, Body>(https);
+ Ok(client)
+ }
+
+ fn run_request(
+ request: Request,
+ ) -> Result {
+ let client = Self::build_client()?;
let (tx, rx) = std::sync::mpsc::channel();
@@ -178,6 +183,61 @@ impl HttpClient {
rx.recv().unwrap()
}
+ fn run_download(
+ request: Request,
+ mut output: Box,
+ ) -> Result<(), Error> {
+ let client = Self::build_client()?;
+
+ let (tx, rx) = std::sync::mpsc::channel();
+
+ let future = client
+ .request(request)
+ .map_err(Error::from)
+ .and_then(move |resp| {
+
+ let status = resp.status();
+
+ resp.into_body()
+ .map_err(Error::from)
+ .for_each(move |chunk| {
+ output.write_all(&chunk)?;
+ Ok(())
+ })
+
+ })
+ .then(move |res| {
+ tx.send(res).unwrap();
+ Ok(())
+ });
+
+ // drop client, else client keeps connectioon open (keep-alive feature)
+ drop(client);
+
+ rt::run(future);
+
+ rx.recv().unwrap()
+ }
+
+ pub fn download(&mut self, path: &str, output: Box) -> Result<(), Error> {
+
+ let path = path.trim_matches('/');
+ let url: Uri = format!("https://{}:8007/{}", self.server, path).parse()?;
+
+ let (ticket, _token) = self.login()?;
+
+ let enc_ticket = percent_encode(ticket.as_bytes(), DEFAULT_ENCODE_SET).to_string();
+
+ let request = Request::builder()
+ .method("GET")
+ .uri(url)
+ .header("User-Agent", "proxmox-backup-client/1.0")
+ .header("Cookie", format!("PBSAuthCookie={}", enc_ticket))
+ .body(Body::empty())?;
+
+ Self::run_download(request, output)
+ }
+
pub fn get(&mut self, path: &str) -> Result {
let path = path.trim_matches('/');