1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
use std::io::Error as IoError;
use std::io::ErrorKind;
use std::time::Duration;
use futures::StreamExt;
use hyper::client::HttpConnector;
use hyper::{Body, Client as HyperClient, Request, Uri};
use tokio::time;
#[derive(Debug, Clone)]
pub struct HttpClient {
inner: HyperClient<HttpConnector>,
}
impl HttpClient {
pub fn new() -> HttpClient {
HttpClient {
inner: HyperClient::new(),
}
}
pub async fn get(&self, uri: Uri, timeout: Duration) -> Result<String, IoError> {
match Request::get(uri).body(Body::empty()) {
Ok(request) => self.request(request, timeout).await,
Err(err) => Err(IoError::new(
ErrorKind::Other,
format!("Invalid request: {}", err),
)),
}
}
pub async fn request(&self, req: Request<Body>, timeout: Duration) -> Result<String, IoError> {
match time::timeout(timeout, self.inner.request(req)).await {
Err(_elapsed) => Err(IoError::new(ErrorKind::TimedOut, "Request timed out")),
Ok(try_resp) => {
let mut resp = try_resp.map_err(|err| {
IoError::new(ErrorKind::Other, format!("Response failed: {}", err))
})?;
let body = resp.body_mut();
let mut text = vec![];
while let Some(chunk) = body.next().await {
let chunk = chunk.map_err(|err| {
IoError::new(ErrorKind::Other, format!("Could not get chunk: {}", err))
})?;
text.extend(chunk.to_vec());
}
String::from_utf8(text)
.map_err(|_| IoError::new(ErrorKind::InvalidData, "Non UTF-8 Data returned"))
}
}
}
}