…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 | mod remote; | 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 | pub struct Curl { | 23 | pub struct Curl { |
| 14 | req: SyncSender<remote::Request>, | 24 | req: SyncSender<remote::Request>, |
| 15 | res: Receiver<remote::Response>, | 25 | res: Receiver<remote::Response>, |
| 16 | handle: Option<thread::JoinHandle<Result<(), curl::Error>>>, | 26 | handle: Option<thread::JoinHandle<Result<(), curl::Error>>>, |
| 27 | options: Options, | ||
| 17 | } | 28 | } |
| 18 | 29 | ||
| 19 | impl Curl { | 30 | impl Curl { |
| @@ -48,6 +59,7 @@ impl Curl { · 28 unmodified lines | |||
| 48 | url: url.to_owned(), | 59 | url: url.to_owned(), |
| 49 | headers: list, | 60 | headers: list, |
| 50 | upload, | 61 | upload, |
| 62 | config: self.options.clone(), | ||
| 51 | }) | 63 | }) |
| 52 | .is_err() | 64 | .is_err() |
| 53 | { | 65 | { |
| @@ -76,6 +88,7 @@ impl Default for Curl { · 22 unmodified lines | |||
| 76 | handle: Some(handle), | 88 | handle: Some(handle), |
| 77 | req, | 89 | req, |
| 78 | res, | 90 | res, |
| 91 | options: Options::default(), | ||
| 79 | } | 92 | } |
| 80 | } | 93 | } |
| 81 | } | 94 | } |
| @@ -92,6 +92,7 @@ pub struct Request { · 91 unmodified lines | |||
| 92 | pub url: String, | 92 | pub url: String, |
| 93 | pub headers: curl::easy::List, | 93 | pub headers: curl::easy::List, |
| 94 | pub upload: bool, | 94 | pub upload: bool, |
| 95 | pub config: http::curl::Options, | ||
| 95 | } | 96 | } |
| 96 | 97 | ||
| 97 | pub struct Response { | 98 | pub struct Response { |
| @@ -110,11 +111,20 @@ pub fn new() -> ( · 12 unmodified lines | |||
| 110 | let handle = std::thread::spawn(move || -> Result<(), curl::Error> { | 111 | let handle = std::thread::spawn(move || -> Result<(), curl::Error> { |
| 111 | let mut handle = Easy2::new(Handler::default()); | 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 | handle.url(&url)?; | 121 | handle.url(&url)?; |
| 115 | 122 | ||
| 116 | // GitHub sends 'chunked' to avoid unknown clients to choke on the data, I suppose | 123 | // GitHub sends 'chunked' to avoid unknown clients to choke on the data, I suppose |
| 117 | handle.post(upload)?; | 124 | handle.post(upload)?; |
| 125 | for header in config.extra_headers { | ||
| 126 | headers.append(&header)?; | ||
| 127 | } | ||
| 118 | handle.http_headers(headers)?; | 128 | handle.http_headers(headers)?; |
| 119 | handle.transfer_encoding(false)?; | 129 | handle.transfer_encoding(false)?; |
| 120 | handle.connect_timeout(Duration::from_secs(20))?; | 130 | handle.connect_timeout(Duration::from_secs(20))?; |
| @@ -21,6 +21,30 @@ mod reqwest; · 20 unmodified lines | |||
| 21 | /// | 21 | /// |
| 22 | mod traits; | 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 | /// The http client configuration when using reqwest | 48 | /// The http client configuration when using reqwest |
| 25 | #[cfg(feature = "http-client-reqwest")] | 49 | #[cfg(feature = "http-client-reqwest")] |
| 26 | pub type Options = reqwest::Options; | 50 | pub type Options = reqwest::Options; |