1+ pub use crate :: client:: http:: reqwest:: remote:: Options ;
2+
13pub struct Remote {
24 /// 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 > > > ,
46 /// A channel to send requests (work) to the worker thread.
57 request : std:: sync:: mpsc:: SyncSender < remote:: Request > ,
68 /// A channel to receive the result of the prior request.
79 response : std:: sync:: mpsc:: Receiver < remote:: Response > ,
10+ /// A mechanism for configuring the remote.
11+ config : Options ,
812}
913
1014mod 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 } ;
1217
1318 use git_features:: io:: pipe;
1419
1520 use crate :: client:: { http, http:: reqwest:: Remote } ;
1621
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+
1730 impl Default for Remote {
1831 fn default ( ) -> Self {
1932 let ( req_send, req_recv) = std:: sync:: mpsc:: sync_channel ( 0 ) ;
2033 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+ {
2342 // We may error while configuring, which is expected as part of the internal protocol. The error will be
2443 // received and the sender of the request might restart us.
2544 let client = reqwest:: blocking:: ClientBuilder :: new ( )
2645 . connect_timeout ( std:: time:: Duration :: from_secs ( 20 ) )
2746 . 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) ;
2948 let ( post_body_tx, post_body_rx) = pipe:: unidirectional ( 0 ) ;
3049 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) ) ;
3251 }
52+ let mut req = req_builder. build ( ) ?;
3353 let ( mut response_body_tx, response_body_rx) = pipe:: unidirectional ( 0 ) ;
3454 let ( mut headers_tx, headers_rx) = pipe:: unidirectional ( 0 ) ;
3555 if res_send
@@ -44,7 +64,11 @@ mod remote {
4464 // Shut down as something is off.
4565 break ;
4666 }
47- let mut res = match req. send ( ) . and_then ( |res| res. error_for_status ( ) ) {
67+ if let Some ( mutex) = config. configure_request {
68+ let mut configure_request = mutex. lock ( ) . expect ( "our thread cannot ordinarily panic" ) ;
69+ configure_request ( & mut req) ?;
70+ }
71+ let mut res = match client. execute ( req) . and_then ( |res| res. error_for_status ( ) ) {
4872 Ok ( res) => res,
4973 Err ( err) => {
5074 let ( kind, err) = match err. status ( ) {
@@ -96,6 +120,7 @@ mod remote {
96120 handle : Some ( handle) ,
97121 request : req_send,
98122 response : res_recv,
123+ config : Options :: default ( ) ,
99124 }
100125 }
101126 }
@@ -130,6 +155,7 @@ mod remote {
130155 url : url. to_owned ( ) ,
131156 headers : header_map,
132157 upload,
158+ config : self . config . clone ( ) ,
133159 } )
134160 . expect ( "the remote cannot be down at this point" ) ;
135161
@@ -181,15 +207,37 @@ mod remote {
181207 self . make_request ( url, headers, true )
182208 }
183209
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+ }
185214 Ok ( ( ) )
186215 }
187216 }
188217
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+
189236 pub struct Request {
190237 pub url : String ,
191238 pub headers : reqwest:: header:: HeaderMap ,
192239 pub upload : bool ,
240+ pub config : Options ,
193241 }
194242
195243 /// A link to a thread who provides data for the contained readers.
0 commit comments