diff --git a/proxmox-http/src/client/sync.rs b/proxmox-http/src/client/sync.rs index b8d86f24..7657e348 100644 --- a/proxmox-http/src/client/sync.rs +++ b/proxmox-http/src/client/sync.rs @@ -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, Error> { + body: Option<&[u8]>, + ) -> Result>, 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>) -> Result, Error> { + let (parts, body) = res.into_parts(); + let body = String::from_utf8(body)?; + Ok(Response::from_parts(parts, body)) + } } impl HttpClient for Client { @@ -75,6 +84,7 @@ impl HttpClient for Client { } self.exec_request(req, None) + .and_then(Self::convert_body_to_string) } fn post( @@ -88,7 +98,8 @@ impl HttpClient 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) -> Result, Error> { @@ -103,6 +114,54 @@ impl HttpClient 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> for Client { + fn get( + &self, + uri: &str, + extra_headers: Option<&HashMap>, + ) -> Result>, 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>, 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>) -> Result>, 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())) } }