omaha_client_fuchsia/
http_request.rs1use fuchsia_async::TimeoutExt;
6use futures::future::BoxFuture;
7use futures::prelude::*;
8use hyper::client::ResponseFuture;
9use hyper::{Body, Client, Request, Response};
10use omaha_client::http_request::{Error, HttpRequest};
11use std::time::Duration;
12
13pub struct FuchsiaHyperHttpRequest {
14 timeout: Duration,
15 client: Client<hyper_rustls::HttpsConnector<fuchsia_hyper::HyperConnector>, Body>,
16}
17
18impl HttpRequest for FuchsiaHyperHttpRequest {
19 fn request(&mut self, req: Request<Body>) -> BoxFuture<'_, Result<Response<Vec<u8>>, Error>> {
20 let response = self.client.request(req);
22 let timeout = self.timeout;
23
24 collect_from_future(response).on_timeout(timeout, || Err(Error::new_timeout())).boxed()
25 }
26}
27
28async fn collect_from_future(response_future: ResponseFuture) -> Result<Response<Vec<u8>>, Error> {
30 let response = response_future.await.map_err(Error::from)?;
31 let (parts, body) = response.into_parts();
32 let bytes = hyper::body::to_bytes(body).await?;
33 Ok(Response::from_parts(parts, bytes.to_vec()))
34}
35
36impl FuchsiaHyperHttpRequest {
37 pub fn new() -> Self {
39 Self::using_timeout(Duration::from_secs(30))
40 }
41
42 pub fn using_timeout(timeout: Duration) -> Self {
44 FuchsiaHyperHttpRequest { timeout, client: fuchsia_hyper::new_https_client() }
45 }
46}
47
48#[cfg(test)]
49mod tests {
50 use super::*;
51 use fuchsia_hyper_test_support::TestServer;
52 use fuchsia_hyper_test_support::fault_injection::{Hang, HangBody};
53 use fuchsia_hyper_test_support::handler::StaticResponse;
54
55 fn make_request_for(server: &TestServer, path: &str) -> Request<Body> {
57 Request::builder().uri(server.local_url_for_path(path)).body(Body::empty()).unwrap()
58 }
59
60 #[fuchsia_async::run_singlethreaded(test)]
63 async fn test_simple_request() {
64 let server =
65 TestServer::builder().handler(StaticResponse::ok_body("some data")).start().await;
66 let mut client = FuchsiaHyperHttpRequest::using_timeout(Duration::from_secs(5));
67 let response = client.request(make_request_for(&server, "some/path")).await.unwrap();
68 let string = String::from_utf8(response.into_body()).unwrap();
69 assert_eq!(string, "some data");
70 }
71
72 #[fuchsia_async::run_singlethreaded(test)]
75 async fn test_hang() {
76 let server = TestServer::builder().handler(Hang).start().await;
77 let mut client = FuchsiaHyperHttpRequest::using_timeout(Duration::from_secs(1));
78 let response = client.request(make_request_for(&server, "some/path")).await;
79 assert!(response.unwrap_err().is_timeout());
80 }
81
82 #[fuchsia_async::run_singlethreaded(test)]
85 async fn test_hang_body() {
86 let server = TestServer::builder().handler(HangBody::content_length(500)).start().await;
87 let mut client = FuchsiaHyperHttpRequest::using_timeout(Duration::from_secs(1));
88 let response = client.request(make_request_for(&server, "some/path")).await;
89 assert!(response.unwrap_err().is_timeout());
90 }
91}