@@ -5,52 +5,66 @@ use futures_util::stream::TryStreamExt;
55use http_types:: headers:: { HeaderName , HeaderValue } ;
66use http_types:: StatusCode ;
77use hyper:: body:: HttpBody ;
8+ use hyper:: client:: connect:: Connect ;
89use hyper_tls:: HttpsConnector ;
910use std:: convert:: TryFrom ;
11+ use std:: fmt:: Debug ;
1012use std:: io;
1113use std:: str:: FromStr ;
1214
15+ type HyperRequest = hyper:: Request < hyper:: Body > ;
16+
17+ // Avoid leaking Hyper generics into HttpClient by hiding it behind a dynamic trait object pointer.
18+ trait HyperClientObject : Debug + Send + Sync + ' static {
19+ fn dyn_request ( & self , req : hyper:: Request < hyper:: Body > ) -> hyper:: client:: ResponseFuture ;
20+ }
21+
22+ impl < C : Clone + Connect + Debug + Send + Sync + ' static > HyperClientObject for hyper:: Client < C > {
23+ fn dyn_request ( & self , req : HyperRequest ) -> hyper:: client:: ResponseFuture {
24+ self . request ( req)
25+ }
26+ }
27+
1328/// Hyper-based HTTP Client.
1429#[ derive( Debug ) ]
15- pub struct HyperClient { }
30+ pub struct HyperClient ( Box < dyn HyperClientObject > ) ;
1631
1732impl HyperClient {
18- /// Create a new client.
19- ///
20- /// There is no specific benefit to reusing instances of this client.
33+ /// Create a new client instance.
2134 pub fn new ( ) -> Self {
22- HyperClient { }
35+ let https = HttpsConnector :: new ( ) ;
36+ let client = hyper:: Client :: builder ( ) . build ( https) ;
37+ Self ( Box :: new ( client) )
38+ }
39+
40+ /// Create from externally initialized and configured client.
41+ pub fn from_client < C > ( client : hyper:: Client < C > ) -> Self
42+ where
43+ C : Clone + Connect + Debug + Send + Sync + ' static ,
44+ {
45+ Self ( Box :: new ( client) )
46+ }
47+ }
48+
49+ impl Default for HyperClient {
50+ fn default ( ) -> Self {
51+ Self :: new ( )
2352 }
2453}
2554
2655#[ async_trait]
2756impl HttpClient for HyperClient {
2857 async fn send ( & self , req : Request ) -> Result < Response , Error > {
2958 let req = HyperHttpRequest :: try_from ( req) . await ?. into_inner ( ) ;
30- // UNWRAP: Scheme guaranteed to be "http" or "https" as part of conversion
31- let scheme = req. uri ( ) . scheme_str ( ) . unwrap ( ) ;
3259
33- let response = match scheme {
34- "http" => {
35- let client = hyper:: Client :: builder ( ) . build_http :: < hyper:: Body > ( ) ;
36- client. request ( req) . await
37- }
38- "https" => {
39- let https = HttpsConnector :: new ( ) ;
40- let client = hyper:: Client :: builder ( ) . build :: < _ , hyper:: Body > ( https) ;
41- client. request ( req) . await
42- }
43- _ => unreachable ! ( ) ,
44- } ?;
60+ let response = self . 0 . dyn_request ( req) . await ?;
4561
46- let resp = HttpTypesResponse :: try_from ( response) . await ?. into_inner ( ) ;
47- Ok ( resp )
62+ let res = HttpTypesResponse :: try_from ( response) . await ?. into_inner ( ) ;
63+ Ok ( res )
4864 }
4965}
5066
51- struct HyperHttpRequest {
52- inner : hyper:: Request < hyper:: Body > ,
53- }
67+ struct HyperHttpRequest ( HyperRequest ) ;
5468
5569impl HyperHttpRequest {
5670 async fn try_from ( mut value : Request ) -> Result < Self , Error > {
@@ -88,17 +102,15 @@ impl HyperHttpRequest {
88102 . uri ( uri)
89103 . body ( body) ?;
90104
91- Ok ( HyperHttpRequest { inner : request } )
105+ Ok ( HyperHttpRequest ( request) )
92106 }
93107
94108 fn into_inner ( self ) -> hyper:: Request < hyper:: Body > {
95- self . inner
109+ self . 0
96110 }
97111}
98112
99- struct HttpTypesResponse {
100- inner : Response ,
101- }
113+ struct HttpTypesResponse ( Response ) ;
102114
103115impl HttpTypesResponse {
104116 async fn try_from ( value : hyper:: Response < hyper:: Body > ) -> Result < Self , Error > {
@@ -123,11 +135,11 @@ impl HttpTypesResponse {
123135 }
124136
125137 res. set_body ( body) ;
126- Ok ( HttpTypesResponse { inner : res } )
138+ Ok ( HttpTypesResponse ( res) )
127139 }
128140
129141 fn into_inner ( self ) -> Response {
130- self . inner
142+ self . 0
131143 }
132144}
133145
0 commit comments