| use crate::{ |
| config, |
| config::tree::{keys, Http, Key, Section}, |
| }; |
| |
| impl Http { |
| /// The `http.sslVersion` key. |
| pub const SSL_VERSION: SslVersion = SslVersion::new_ssl_version("sslVersion", &config::Tree::HTTP) |
| .with_environment_override("GIT_SSL_VERSION") |
| .with_deviation( |
| "accepts the new 'default' value which means to use the curl default just like the empty string does", |
| ); |
| /// The `http.sslVerify` key. |
| pub const SSL_VERIFY: keys::Boolean = keys::Boolean::new_boolean("sslVerify", &config::Tree::HTTP) |
| .with_note("also see the `gitoxide.http.sslNoVerify` key"); |
| /// The `http.proxy` key. |
| pub const PROXY: keys::String = |
| keys::String::new_string("proxy", &config::Tree::HTTP).with_deviation("fails on strings with illformed UTF-8"); |
| /// The `http.proxyAuthMethod` key. |
| pub const PROXY_AUTH_METHOD: ProxyAuthMethod = |
| ProxyAuthMethod::new_proxy_auth_method("proxyAuthMethod", &config::Tree::HTTP) |
| .with_deviation("implemented like git, but never actually tried"); |
| /// The `http.version` key. |
| pub const VERSION: Version = Version::new_with_validate("version", &config::Tree::HTTP, validate::Version) |
| .with_deviation("fails on illformed UTF-8"); |
| /// The `http.userAgent` key. |
| pub const USER_AGENT: keys::String = |
| keys::String::new_string("userAgent", &config::Tree::HTTP).with_deviation("fails on illformed UTF-8"); |
| /// The `http.extraHeader` key. |
| pub const EXTRA_HEADER: ExtraHeader = |
| ExtraHeader::new_with_validate("extraHeader", &config::Tree::HTTP, validate::ExtraHeader) |
| .with_deviation("fails on illformed UTF-8, without leniency"); |
| /// The `http.followRedirects` key. |
| pub const FOLLOW_REDIRECTS: FollowRedirects = |
| FollowRedirects::new_with_validate("followRedirects", &config::Tree::HTTP, validate::FollowRedirects); |
| /// The `http.lowSpeedTime` key. |
| pub const LOW_SPEED_TIME: keys::UnsignedInteger = |
| keys::UnsignedInteger::new_unsigned_integer("lowSpeedTime", &config::Tree::HTTP) |
| .with_deviation("fails on negative values"); |
| /// The `http.lowSpeedLimit` key. |
| pub const LOW_SPEED_LIMIT: keys::UnsignedInteger = |
| keys::UnsignedInteger::new_unsigned_integer("lowSpeedLimit", &config::Tree::HTTP) |
| .with_deviation("fails on negative values"); |
| /// The `http.schannelUseSSLCAInfo` key. |
| pub const SCHANNEL_USE_SSL_CA_INFO: keys::Boolean = |
| keys::Boolean::new_boolean("schannelUseSSLCAInfo", &config::Tree::HTTP) |
| .with_deviation("only used as switch internally to turn off using the sslCAInfo, unconditionally. If unset, it has no effect, whereas in `git` it defaults to false."); |
| /// The `http.sslCAInfo` key. |
| pub const SSL_CA_INFO: keys::Path = |
| keys::Path::new_path("sslCAInfo", &config::Tree::HTTP).with_environment_override("GIT_SSL_CAINFO"); |
| /// The `http.schannelCheckRevoke` key. |
| pub const SCHANNEL_CHECK_REVOKE: keys::Boolean = |
| keys::Boolean::new_boolean("schannelCheckRevoke", &config::Tree::HTTP); |
| } |
| |
| impl Section for Http { |
| fn name(&self) -> &str { |
| "http" |
| } |
| |
| fn keys(&self) -> &[&dyn Key] { |
| &[ |
| &Self::SSL_VERSION, |
| &Self::SSL_VERIFY, |
| &Self::PROXY, |
| &Self::PROXY_AUTH_METHOD, |
| &Self::VERSION, |
| &Self::USER_AGENT, |
| &Self::EXTRA_HEADER, |
| &Self::FOLLOW_REDIRECTS, |
| &Self::LOW_SPEED_TIME, |
| &Self::LOW_SPEED_LIMIT, |
| &Self::SCHANNEL_USE_SSL_CA_INFO, |
| &Self::SSL_CA_INFO, |
| &Self::SCHANNEL_CHECK_REVOKE, |
| ] |
| } |
| } |
| |
| /// The `http.followRedirects` key. |
| pub type FollowRedirects = keys::Any<validate::FollowRedirects>; |
| |
| /// The `http.extraHeader` key. |
| pub type ExtraHeader = keys::Any<validate::ExtraHeader>; |
| |
| /// The `http.sslVersion` key, as well as others of the same type. |
| pub type SslVersion = keys::Any<validate::SslVersion>; |
| |
| /// The `http.proxyAuthMethod` key, as well as others of the same type. |
| pub type ProxyAuthMethod = keys::Any<validate::ProxyAuthMethod>; |
| |
| /// The `http.version` key. |
| pub type Version = keys::Any<validate::Version>; |
| |
| mod key_impls { |
| use crate::config::tree::{ |
| http::{ProxyAuthMethod, SslVersion}, |
| keys, Section, |
| }; |
| |
| impl SslVersion { |
| pub const fn new_ssl_version(name: &'static str, section: &'static dyn Section) -> Self { |
| keys::Any::new_with_validate(name, section, super::validate::SslVersion) |
| } |
| } |
| |
| impl ProxyAuthMethod { |
| pub const fn new_proxy_auth_method(name: &'static str, section: &'static dyn Section) -> Self { |
| keys::Any::new_with_validate(name, section, super::validate::ProxyAuthMethod) |
| } |
| } |
| |
| #[cfg(any( |
| feature = "blocking-http-transport-reqwest", |
| feature = "blocking-http-transport-curl" |
| ))] |
| impl crate::config::tree::http::FollowRedirects { |
| /// Convert `value` into the redirect specification, or query the same value as `boolean` |
| /// for additional possible input values. |
| /// |
| /// Note that `boolean` only queries the underlying key as boolean, which is a necessity to handle |
| /// empty booleans correctly, that is those without a value separator. |
| pub fn try_into_follow_redirects( |
| &'static self, |
| value: std::borrow::Cow<'_, crate::bstr::BStr>, |
| boolean: impl FnOnce() -> Result<Option<bool>, gix_config::value::Error>, |
| ) -> Result< |
| crate::protocol::transport::client::http::options::FollowRedirects, |
| crate::config::key::GenericErrorWithValue, |
| > { |
| use crate::{bstr::ByteSlice, protocol::transport::client::http::options::FollowRedirects}; |
| Ok(if value.as_ref().as_bytes() == b"initial" { |
| FollowRedirects::Initial |
| } else if let Some(value) = boolean().map_err(|err| { |
| crate::config::key::GenericErrorWithValue::from_value(self, value.into_owned()).with_source(err) |
| })? { |
| if value { |
| FollowRedirects::All |
| } else { |
| FollowRedirects::None |
| } |
| } else { |
| FollowRedirects::Initial |
| }) |
| } |
| } |
| |
| impl super::ExtraHeader { |
| /// Convert a list of values into extra-headers, while failing entirely on illformed UTF-8. |
| pub fn try_into_extra_header( |
| &'static self, |
| values: Vec<std::borrow::Cow<'_, crate::bstr::BStr>>, |
| ) -> Result<Vec<String>, crate::config::string::Error> { |
| let mut out = Vec::with_capacity(values.len()); |
| for value in values { |
| if value.is_empty() { |
| out.clear(); |
| } else { |
| out.push(self.try_into_string(value)?); |
| } |
| } |
| Ok(out) |
| } |
| } |
| |
| #[cfg(any( |
| feature = "blocking-http-transport-reqwest", |
| feature = "blocking-http-transport-curl" |
| ))] |
| impl super::Version { |
| pub fn try_into_http_version( |
| &'static self, |
| value: std::borrow::Cow<'_, crate::bstr::BStr>, |
| ) -> Result< |
| gix_protocol::transport::client::http::options::HttpVersion, |
| crate::config::key::GenericErrorWithValue, |
| > { |
| use gix_protocol::transport::client::http::options::HttpVersion; |
| |
| use crate::bstr::ByteSlice; |
| Ok(match value.as_ref().as_bytes() { |
| b"HTTP/1.1" => HttpVersion::V1_1, |
| b"HTTP/2" => HttpVersion::V2, |
| _ => { |
| return Err(crate::config::key::GenericErrorWithValue::from_value( |
| self, |
| value.into_owned(), |
| )) |
| } |
| }) |
| } |
| } |
| |
| #[cfg(any( |
| feature = "blocking-http-transport-reqwest", |
| feature = "blocking-http-transport-curl" |
| ))] |
| impl ProxyAuthMethod { |
| pub fn try_into_proxy_auth_method( |
| &'static self, |
| value: std::borrow::Cow<'_, crate::bstr::BStr>, |
| ) -> Result< |
| gix_protocol::transport::client::http::options::ProxyAuthMethod, |
| crate::config::key::GenericErrorWithValue, |
| > { |
| use gix_protocol::transport::client::http::options::ProxyAuthMethod; |
| |
| use crate::bstr::ByteSlice; |
| Ok(match value.as_ref().as_bytes() { |
| b"anyauth" => ProxyAuthMethod::AnyAuth, |
| b"basic" => ProxyAuthMethod::Basic, |
| b"digest" => ProxyAuthMethod::Digest, |
| b"negotiate" => ProxyAuthMethod::Negotiate, |
| b"ntlm" => ProxyAuthMethod::Ntlm, |
| _ => { |
| return Err(crate::config::key::GenericErrorWithValue::from_value( |
| self, |
| value.into_owned(), |
| )) |
| } |
| }) |
| } |
| } |
| |
| #[cfg(any( |
| feature = "blocking-http-transport-reqwest", |
| feature = "blocking-http-transport-curl" |
| ))] |
| impl SslVersion { |
| pub fn try_into_ssl_version( |
| &'static self, |
| value: std::borrow::Cow<'_, crate::bstr::BStr>, |
| ) -> Result<gix_protocol::transport::client::http::options::SslVersion, crate::config::ssl_version::Error> |
| { |
| use gix_protocol::transport::client::http::options::SslVersion::*; |
| |
| use crate::bstr::ByteSlice; |
| Ok(match value.as_ref().as_bytes() { |
| b"default" | b"" => Default, |
| b"tlsv1" => TlsV1, |
| b"sslv2" => SslV2, |
| b"sslv3" => SslV3, |
| b"tlsv1.0" => TlsV1_0, |
| b"tlsv1.1" => TlsV1_1, |
| b"tlsv1.2" => TlsV1_2, |
| b"tlsv1.3" => TlsV1_3, |
| _ => return Err(crate::config::ssl_version::Error::from_value(self, value.into_owned())), |
| }) |
| } |
| } |
| } |
| |
| pub mod validate { |
| use std::error::Error; |
| |
| use crate::{ |
| bstr::{BStr, ByteSlice}, |
| config::tree::keys::Validate, |
| }; |
| |
| pub struct SslVersion; |
| impl Validate for SslVersion { |
| fn validate(&self, _value: &BStr) -> Result<(), Box<dyn Error + Send + Sync + 'static>> { |
| #[cfg(any( |
| feature = "blocking-http-transport-reqwest", |
| feature = "blocking-http-transport-curl" |
| ))] |
| super::Http::SSL_VERSION.try_into_ssl_version(std::borrow::Cow::Borrowed(_value))?; |
| |
| Ok(()) |
| } |
| } |
| |
| pub struct ProxyAuthMethod; |
| impl Validate for ProxyAuthMethod { |
| fn validate(&self, _value: &BStr) -> Result<(), Box<dyn Error + Send + Sync + 'static>> { |
| #[cfg(any( |
| feature = "blocking-http-transport-reqwest", |
| feature = "blocking-http-transport-curl" |
| ))] |
| super::Http::PROXY_AUTH_METHOD.try_into_proxy_auth_method(std::borrow::Cow::Borrowed(_value))?; |
| |
| Ok(()) |
| } |
| } |
| |
| pub struct Version; |
| impl Validate for Version { |
| fn validate(&self, _value: &BStr) -> Result<(), Box<dyn Error + Send + Sync + 'static>> { |
| #[cfg(any( |
| feature = "blocking-http-transport-reqwest", |
| feature = "blocking-http-transport-curl" |
| ))] |
| super::Http::VERSION.try_into_http_version(std::borrow::Cow::Borrowed(_value))?; |
| |
| Ok(()) |
| } |
| } |
| |
| pub struct ExtraHeader; |
| impl Validate for ExtraHeader { |
| fn validate(&self, value: &BStr) -> Result<(), Box<dyn Error + Send + Sync + 'static>> { |
| value.to_str()?; |
| Ok(()) |
| } |
| } |
| |
| pub struct FollowRedirects; |
| impl Validate for FollowRedirects { |
| fn validate(&self, _value: &BStr) -> Result<(), Box<dyn Error + Send + Sync + 'static>> { |
| #[cfg(any( |
| feature = "blocking-http-transport-reqwest", |
| feature = "blocking-http-transport-curl" |
| ))] |
| super::Http::FOLLOW_REDIRECTS.try_into_follow_redirects(std::borrow::Cow::Borrowed(_value), || { |
| gix_config::Boolean::try_from(_value).map(|b| Some(b.0)) |
| })?; |
| Ok(()) |
| } |
| } |
| } |