…but it clearly shows that the backend needs to be abstracted or else we can't have general HTTP options as are implied by the way git works.
Unified · Split
| @@ -10,10 +10,21 @@ use crate::client::blocking_io::http; · 9 unmodified lines | ||
| 10 | 10 | |
| 11 | 11 | mod remote; |
| 12 | 12 | |
| 13 | +/// Options to configure curl requests. | |
| 14 | +#[derive(Default, Clone)] | |
| 15 | +pub struct Options { | |
| 16 | + /// Corresponds to the `http.extraHeader` configuration, a multi-var. | |
| 17 | + /// They are applied unconditionally and are expected to be valid. | |
| 18 | + pub extra_headers: Vec<String>, | |
| 19 | + /// How to handle redirects. | |
| 20 | + pub follow_redirects: http::options::FollowRedirects, | |
| 21 | +} | |
| 22 | + | |
| 13 | 23 | pub struct Curl { |
| 14 | 24 | req: SyncSender<remote::Request>, |
| 15 | 25 | res: Receiver<remote::Response>, |
| 16 | 26 | handle: Option<thread::JoinHandle<Result<(), curl::Error>>>, |
| 27 | + options: Options, | |
| 17 | 28 | } |
| 18 | 29 | |
| 19 | 30 | impl Curl { |
| @@ -48,6 +59,7 @@ impl Curl { · 28 unmodified lines | ||
| 48 | 59 | url: url.to_owned(), |
| 49 | 60 | headers: list, |
| 50 | 61 | upload, |
| 62 | + config: self.options.clone(), | |
| 51 | 63 | }) |
| 52 | 64 | .is_err() |
| 53 | 65 | { |
| @@ -76,6 +88,7 @@ impl Default for Curl { · 22 unmodified lines | ||
| 76 | 88 | handle: Some(handle), |
| 77 | 89 | req, |
| 78 | 90 | res, |
| 91 | + options: Options::default(), | |
| 79 | 92 | } |
| 80 | 93 | } |
| 81 | 94 | } |
| @@ -92,6 +92,7 @@ pub struct Request { · 91 unmodified lines | ||
| 92 | 92 | pub url: String, |
| 93 | 93 | pub headers: curl::easy::List, |
| 94 | 94 | pub upload: bool, |
| 95 | + pub config: http::curl::Options, | |
| 95 | 96 | } |
| 96 | 97 | |
| 97 | 98 | pub struct Response { |
| @@ -110,11 +111,20 @@ pub fn new() -> ( · 12 unmodified lines | ||
| 110 | 111 | let handle = std::thread::spawn(move || -> Result<(), curl::Error> { |
| 111 | 112 | let mut handle = Easy2::new(Handler::default()); |
| 112 | 113 | |
| 113 | − for Request { url, headers, upload } in req_recv { | |
| 114 | + for Request { | |
| 115 | + url, | |
| 116 | + mut headers, | |
| 117 | + upload, | |
| 118 | + config, | |
| 119 | + } in req_recv | |
| 120 | + { | |
| 114 | 121 | handle.url(&url)?; |
| 115 | 122 | |
| 116 | 123 | // GitHub sends 'chunked' to avoid unknown clients to choke on the data, I suppose |
| 117 | 124 | handle.post(upload)?; |
| 125 | + for header in config.extra_headers { | |
| 126 | + headers.append(&header)?; | |
| 127 | + } | |
| 118 | 128 | handle.http_headers(headers)?; |
| 119 | 129 | handle.transfer_encoding(false)?; |
| 120 | 130 | handle.connect_timeout(Duration::from_secs(20))?; |
| @@ -21,6 +21,30 @@ mod reqwest; · 20 unmodified lines | ||
| 21 | 21 | /// |
| 22 | 22 | mod traits; |
| 23 | 23 | |
| 24 | +/// | |
| 25 | +pub mod options { | |
| 26 | + /// possible settings for the `http.followRedirects` configuration option. | |
| 27 | + #[derive(Copy, Clone, PartialEq, Eq)] | |
| 28 | + pub enum FollowRedirects { | |
| 29 | + /// Follow only the first redirect request, most suitable for typical git requests. | |
| 30 | + Initial, | |
| 31 | + /// Follow all redirect requests from the server unconditionally | |
| 32 | + All, | |
| 33 | + /// Follow no redirect request. | |
| 34 | + None, | |
| 35 | + } | |
| 36 | + | |
| 37 | + impl Default for FollowRedirects { | |
| 38 | + fn default() -> Self { | |
| 39 | + FollowRedirects::Initial | |
| 40 | + } | |
| 41 | + } | |
| 42 | +} | |
| 43 | + | |
| 44 | +/// The http client configuration when using reqwest | |
| 45 | +#[cfg(feature = "http-client-curl")] | |
| 46 | +pub type Options = curl::Options; | |
| 47 | + | |
| 24 | 48 | /// The http client configuration when using reqwest |
| 25 | 49 | #[cfg(feature = "http-client-reqwest")] |
| 26 | 50 | pub type Options = reqwest::Options; |