1
1
//! http-client implementation for async-h1, with connecton pooling ("Keep-Alive").
2
2
3
+ #[ cfg( feature = "unstable-config" ) ]
4
+ use std:: convert:: { Infallible , TryFrom } ;
5
+
3
6
use std:: fmt:: Debug ;
4
7
use std:: net:: SocketAddr ;
5
8
@@ -17,6 +20,8 @@ cfg_if::cfg_if! {
17
20
}
18
21
}
19
22
23
+ use crate :: Config ;
24
+
20
25
use super :: { async_trait, Error , HttpClient , Request , Response } ;
21
26
22
27
mod tcp;
@@ -40,6 +45,7 @@ pub struct H1Client {
40
45
#[ cfg( any( feature = "native-tls" , feature = "rustls" ) ) ]
41
46
https_pools : HttpsPool ,
42
47
max_concurrent_connections : usize ,
48
+ config : Config ,
43
49
}
44
50
45
51
impl Debug for H1Client {
@@ -75,6 +81,7 @@ impl Debug for H1Client {
75
81
. collect :: < Vec < String > > ( ) ,
76
82
)
77
83
. field ( "https_pools" , & https_pools)
84
+ . field ( "config" , & self . config )
78
85
. field (
79
86
"max_concurrent_connections" ,
80
87
& self . max_concurrent_connections ,
@@ -97,6 +104,7 @@ impl H1Client {
97
104
#[ cfg( any( feature = "native-tls" , feature = "rustls" ) ) ]
98
105
https_pools : DashMap :: new ( ) ,
99
106
max_concurrent_connections : DEFAULT_MAX_CONCURRENT_CONNECTIONS ,
107
+ config : Config :: default ( ) ,
100
108
}
101
109
}
102
110
@@ -107,6 +115,7 @@ impl H1Client {
107
115
#[ cfg( any( feature = "native-tls" , feature = "rustls" ) ) ]
108
116
https_pools : DashMap :: new ( ) ,
109
117
max_concurrent_connections : max,
118
+ config : Config :: default ( ) ,
110
119
}
111
120
}
112
121
}
@@ -152,7 +161,7 @@ impl HttpClient for H1Client {
152
161
let pool_ref = if let Some ( pool_ref) = self . http_pools . get ( & addr) {
153
162
pool_ref
154
163
} else {
155
- let manager = TcpConnection :: new ( addr) ;
164
+ let manager = TcpConnection :: new ( addr, self . config . clone ( ) ) ;
156
165
let pool = Pool :: < TcpStream , std:: io:: Error > :: new (
157
166
manager,
158
167
self . max_concurrent_connections ,
@@ -168,19 +177,28 @@ impl HttpClient for H1Client {
168
177
let stream = match pool. get ( ) . await {
169
178
Ok ( s) => s,
170
179
Err ( _) if has_another_addr => continue ,
171
- Err ( e) => return Err ( Error :: from_str ( 400 , e. to_string ( ) ) ) ? ,
180
+ Err ( e) => return Err ( Error :: from_str ( 400 , e. to_string ( ) ) ) ,
172
181
} ;
173
182
174
183
req. set_peer_addr ( stream. peer_addr ( ) . ok ( ) ) ;
175
184
req. set_local_addr ( stream. local_addr ( ) . ok ( ) ) ;
176
- return client:: connect ( TcpConnWrapper :: new ( stream) , req) . await ;
185
+
186
+ let tcp_conn = client:: connect ( TcpConnWrapper :: new ( stream) , req) ;
187
+ #[ cfg( feature = "unstable-config" ) ]
188
+ return if let Some ( timeout) = self . config . timeout {
189
+ async_std:: future:: timeout ( timeout, tcp_conn) . await ?
190
+ } else {
191
+ tcp_conn. await
192
+ } ;
193
+ #[ cfg( not( feature = "unstable-config" ) ) ]
194
+ return tcp_conn. await ;
177
195
}
178
196
#[ cfg( any( feature = "native-tls" , feature = "rustls" ) ) ]
179
197
"https" => {
180
198
let pool_ref = if let Some ( pool_ref) = self . https_pools . get ( & addr) {
181
199
pool_ref
182
200
} else {
183
- let manager = TlsConnection :: new ( host. clone ( ) , addr) ;
201
+ let manager = TlsConnection :: new ( host. clone ( ) , addr, self . config . clone ( ) ) ;
184
202
let pool = Pool :: < TlsStream < TcpStream > , Error > :: new (
185
203
manager,
186
204
self . max_concurrent_connections ,
@@ -196,13 +214,21 @@ impl HttpClient for H1Client {
196
214
let stream = match pool. get ( ) . await {
197
215
Ok ( s) => s,
198
216
Err ( _) if has_another_addr => continue ,
199
- Err ( e) => return Err ( Error :: from_str ( 400 , e. to_string ( ) ) ) ? ,
217
+ Err ( e) => return Err ( Error :: from_str ( 400 , e. to_string ( ) ) ) ,
200
218
} ;
201
219
202
220
req. set_peer_addr ( stream. get_ref ( ) . peer_addr ( ) . ok ( ) ) ;
203
221
req. set_local_addr ( stream. get_ref ( ) . local_addr ( ) . ok ( ) ) ;
204
222
205
- return client:: connect ( TlsConnWrapper :: new ( stream) , req) . await ;
223
+ let tls_conn = client:: connect ( TlsConnWrapper :: new ( stream) , req) ;
224
+ #[ cfg( feature = "unstable-config" ) ]
225
+ return if let Some ( timeout) = self . config . timeout {
226
+ async_std:: future:: timeout ( timeout, tls_conn) . await ?
227
+ } else {
228
+ tls_conn. await
229
+ } ;
230
+ #[ cfg( not( feature = "unstable-config" ) ) ]
231
+ return tls_conn. await ;
206
232
}
207
233
_ => unreachable ! ( ) ,
208
234
}
@@ -213,6 +239,37 @@ impl HttpClient for H1Client {
213
239
"missing valid address" ,
214
240
) )
215
241
}
242
+
243
+ #[ cfg( feature = "unstable-config" ) ]
244
+ /// Override the existing configuration with new configuration.
245
+ ///
246
+ /// Config options may not impact existing connections.
247
+ fn set_config ( & mut self , config : Config ) -> http_types:: Result < ( ) > {
248
+ self . config = config;
249
+
250
+ Ok ( ( ) )
251
+ }
252
+
253
+ #[ cfg( feature = "unstable-config" ) ]
254
+ /// Get the current configuration.
255
+ fn config ( & self ) -> & Config {
256
+ & self . config
257
+ }
258
+ }
259
+
260
+ #[ cfg( feature = "unstable-config" ) ]
261
+ impl TryFrom < Config > for H1Client {
262
+ type Error = Infallible ;
263
+
264
+ fn try_from ( config : Config ) -> Result < Self , Self :: Error > {
265
+ Ok ( Self {
266
+ http_pools : DashMap :: new ( ) ,
267
+ #[ cfg( any( feature = "native-tls" , feature = "rustls" ) ) ]
268
+ https_pools : DashMap :: new ( ) ,
269
+ max_concurrent_connections : DEFAULT_MAX_CONCURRENT_CONNECTIONS ,
270
+ config,
271
+ } )
272
+ }
216
273
}
217
274
218
275
#[ cfg( test) ]
0 commit comments