1
+ pub use crate :: client:: http:: reqwest:: remote:: Options ;
2
+
1
3
pub struct Remote {
2
4
/// A worker thread which performs the actual request.
3
- handle : Option < std:: thread:: JoinHandle < Result < ( ) , reqwest :: Error > > > ,
5
+ handle : Option < std:: thread:: JoinHandle < Result < ( ) , remote :: Error > > > ,
4
6
/// A channel to send requests (work) to the worker thread.
5
7
request : std:: sync:: mpsc:: SyncSender < remote:: Request > ,
6
8
/// A channel to receive the result of the prior request.
7
9
response : std:: sync:: mpsc:: Receiver < remote:: Response > ,
10
+ /// A mechanism for configuring the remote.
11
+ config : Options ,
8
12
}
9
13
10
14
mod remote {
11
- use std:: { any:: Any , convert:: TryFrom , error:: Error , io:: Write , str:: FromStr } ;
15
+ use std:: sync:: { Arc , Mutex } ;
16
+ use std:: { any:: Any , convert:: TryFrom , io:: Write , str:: FromStr } ;
12
17
13
18
use git_features:: io:: pipe;
14
19
15
20
use crate :: client:: { http, http:: reqwest:: Remote } ;
16
21
22
+ #[ derive( Debug , thiserror:: Error ) ]
23
+ pub enum Error {
24
+ #[ error( transparent) ]
25
+ Reqwest ( #[ from] reqwest:: Error ) ,
26
+ #[ error( "Request configuration failed" ) ]
27
+ ConfigureRequest ( #[ from] Box < dyn std:: error:: Error + Send + Sync + ' static > ) ,
28
+ }
29
+
17
30
impl Default for Remote {
18
31
fn default ( ) -> Self {
19
32
let ( req_send, req_recv) = std:: sync:: mpsc:: sync_channel ( 0 ) ;
20
33
let ( res_send, res_recv) = std:: sync:: mpsc:: sync_channel ( 0 ) ;
21
- let handle = std:: thread:: spawn ( move || -> Result < ( ) , reqwest:: Error > {
22
- for Request { url, headers, upload } in req_recv {
34
+ let handle = std:: thread:: spawn ( move || -> Result < ( ) , Error > {
35
+ for Request {
36
+ url,
37
+ headers,
38
+ upload,
39
+ config,
40
+ } in req_recv
41
+ {
23
42
// We may error while configuring, which is expected as part of the internal protocol. The error will be
24
43
// received and the sender of the request might restart us.
25
44
let client = reqwest:: blocking:: ClientBuilder :: new ( )
26
45
. connect_timeout ( std:: time:: Duration :: from_secs ( 20 ) )
27
46
. build ( ) ?;
28
- let mut req = if upload { client. post ( url) } else { client. get ( url) } . headers ( headers) ;
47
+ let mut req_builder = if upload { client. post ( url) } else { client. get ( url) } . headers ( headers) ;
29
48
let ( post_body_tx, post_body_rx) = pipe:: unidirectional ( 0 ) ;
30
49
if upload {
31
- req = req. body ( reqwest:: blocking:: Body :: new ( post_body_rx) ) ;
50
+ req_builder = req_builder. body ( reqwest:: blocking:: Body :: new ( post_body_rx) ) ;
51
+ }
52
+ let mut req = req_builder. build ( ) ?;
53
+ if let Some ( mutex) = config. configure_request {
54
+ let mut configure_request = mutex. lock ( ) . expect ( "our thread cannot ordinarily panic" ) ;
55
+ configure_request ( & mut req) ?;
32
56
}
33
57
let ( mut response_body_tx, response_body_rx) = pipe:: unidirectional ( 0 ) ;
34
58
let ( mut headers_tx, headers_rx) = pipe:: unidirectional ( 0 ) ;
@@ -44,7 +68,7 @@ mod remote {
44
68
// Shut down as something is off.
45
69
break ;
46
70
}
47
- let mut res = match req . send ( ) . and_then ( |res| res. error_for_status ( ) ) {
71
+ let mut res = match client . execute ( req ) . and_then ( |res| res. error_for_status ( ) ) {
48
72
Ok ( res) => res,
49
73
Err ( err) => {
50
74
let ( kind, err) = match err. status ( ) {
@@ -96,6 +120,7 @@ mod remote {
96
120
handle : Some ( handle) ,
97
121
request : req_send,
98
122
response : res_recv,
123
+ config : Options :: default ( ) ,
99
124
}
100
125
}
101
126
}
@@ -130,6 +155,7 @@ mod remote {
130
155
url : url. to_owned ( ) ,
131
156
headers : header_map,
132
157
upload,
158
+ config : self . config . clone ( ) ,
133
159
} )
134
160
. expect ( "the remote cannot be down at this point" ) ;
135
161
@@ -181,15 +207,37 @@ mod remote {
181
207
self . make_request ( url, headers, true )
182
208
}
183
209
184
- fn configure ( & mut self , _config : & dyn Any ) -> Result < ( ) , Box < dyn Error + Send + Sync + ' static > > {
210
+ fn configure ( & mut self , config : & dyn Any ) -> Result < ( ) , Box < dyn std:: error:: Error + Send + Sync + ' static > > {
211
+ if let Some ( config) = config. downcast_ref :: < Options > ( ) {
212
+ self . config = config. clone ( ) ;
213
+ }
185
214
Ok ( ( ) )
186
215
}
187
216
}
188
217
218
+ /// Options to configure the reqwest HTTP handler.
219
+ #[ derive( Default , Clone ) ]
220
+ pub struct Options {
221
+ /// A function to configure the request that is about to be made.
222
+ pub configure_request : Option <
223
+ Arc <
224
+ Mutex <
225
+ dyn FnMut (
226
+ & mut reqwest:: blocking:: Request ,
227
+ ) -> Result < ( ) , Box < dyn std:: error:: Error + Send + Sync + ' static > >
228
+ + Send
229
+ + Sync
230
+ + ' static ,
231
+ > ,
232
+ > ,
233
+ > ,
234
+ }
235
+
189
236
pub struct Request {
190
237
pub url : String ,
191
238
pub headers : reqwest:: header:: HeaderMap ,
192
239
pub upload : bool ,
240
+ pub config : Options ,
193
241
}
194
242
195
243
/// A link to a thread who provides data for the contained readers.
0 commit comments