]> git.proxmox.com Git - proxmox.git/commitdiff
http: add "raw" sync client
authorFabian Grünbichler <f.gruenbichler@proxmox.com>
Thu, 4 Aug 2022 09:29:44 +0000 (11:29 +0200)
committerFabian Grünbichler <f.gruenbichler@proxmox.com>
Wed, 7 Sep 2022 07:17:45 +0000 (09:17 +0200)
and switch String one over to use it.

Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
proxmox-http/src/client/sync.rs

index b8d86f2456426adb6c09fce769823d88adfd31a4..7657e348987a04a162a29c1c65df4d8aee768ecc 100644 (file)
@@ -1,4 +1,5 @@
 use std::collections::HashMap;
+use std::io::Read;
 
 use anyhow::{format_err, Error};
 use http::Response;
@@ -31,8 +32,8 @@ impl Client {
     fn exec_request(
         &self,
         req: ureq::Request,
-        body: Option<&str>,
-    ) -> Result<Response<String>, Error> {
+        body: Option<&[u8]>,
+    ) -> Result<Response<Vec<u8>>, Error> {
         let req = req.set(
             "User-Agent",
             self.options
@@ -42,7 +43,7 @@ impl Client {
         );
 
         let res = match body {
-            Some(body) => req.send_string(body),
+            Some(body) => req.send_bytes(body),
             None => req.call(),
         }?;
 
@@ -54,10 +55,18 @@ impl Client {
                 builder = builder.header(header, value);
             }
         }
+        let mut body = Vec::new();
+        res.into_reader().read_to_end(&mut body)?;
         builder
-            .body(res.into_string()?)
+            .body(body)
             .map_err(|err| format_err!("Failed to convert HTTP response - {err}"))
     }
+
+    fn convert_body_to_string(res: Response<Vec<u8>>) -> Result<Response<String>, Error> {
+        let (parts, body) = res.into_parts();
+        let body = String::from_utf8(body)?;
+        Ok(Response::from_parts(parts, body))
+    }
 }
 
 impl HttpClient<String> for Client {
@@ -75,6 +84,7 @@ impl HttpClient<String> for Client {
         }
 
         self.exec_request(req, None)
+            .and_then(Self::convert_body_to_string)
     }
 
     fn post(
@@ -88,7 +98,8 @@ impl HttpClient<String> for Client {
             req = req.set("Content-Type", content_type);
         }
 
-        self.exec_request(req, body)
+        self.exec_request(req, body.map(|b| b.as_bytes()))
+            .and_then(Self::convert_body_to_string)
     }
 
     fn request(&self, request: http::Request<String>) -> Result<Response<String>, Error> {
@@ -103,6 +114,54 @@ impl HttpClient<String> for Client {
             }
         }
 
-        self.exec_request(req, Some(request.body().as_str()))
+        self.exec_request(req, Some(request.body().as_bytes()))
+            .and_then(Self::convert_body_to_string)
+    }
+}
+
+impl HttpClient<Vec<u8>> for Client {
+    fn get(
+        &self,
+        uri: &str,
+        extra_headers: Option<&HashMap<String, String>>,
+    ) -> Result<Response<Vec<u8>>, Error> {
+        let mut req = self.agent()?.get(uri);
+
+        if let Some(extra_headers) = extra_headers {
+            for (header, value) in extra_headers {
+                req = req.set(header, value);
+            }
+        }
+
+        self.exec_request(req, None)
+    }
+
+    fn post(
+        &self,
+        uri: &str,
+        body: Option<&str>,
+        content_type: Option<&str>,
+    ) -> Result<Response<Vec<u8>>, Error> {
+        let mut req = self.agent()?.post(uri);
+        if let Some(content_type) = content_type {
+            req = req.set("Content-Type", content_type);
+        }
+
+        self.exec_request(req, body.map(|b| b.as_bytes()))
+    }
+
+    fn request(&self, request: http::Request<Vec<u8>>) -> Result<Response<Vec<u8>>, Error> {
+        let mut req = self
+            .agent()?
+            .request(request.method().as_str(), &request.uri().to_string());
+        let orig_headers = request.headers();
+
+        for header in orig_headers.keys() {
+            for value in orig_headers.get_all(header) {
+                req = req.set(header.as_str(), value.to_str()?);
+            }
+        }
+
+        self.exec_request(req, Some(request.body()))
     }
 }