diff --git a/src/agent.rs b/src/agent.rs index 515aac8..0c16938 100644 --- a/src/agent.rs +++ b/src/agent.rs @@ -54,6 +54,7 @@ pub(crate) struct AgentConfig { pub timeout_read: Option, pub timeout_write: Option, pub timeout: Option, + pub https_only: bool, pub no_delay: bool, pub redirects: u32, pub redirect_auth_headers: RedirectAuthHeaders, @@ -239,6 +240,7 @@ impl AgentBuilder { timeout_read: None, timeout_write: None, timeout: None, + https_only: false, no_delay: true, redirects: 5, redirect_auth_headers: RedirectAuthHeaders::Never, @@ -293,6 +295,21 @@ impl AgentBuilder { self } + /// Enforce the client to only perform HTTPS requests. + /// This setting also makes the client refuse HTTPS to HTTP redirects. + /// Default is false + /// + /// Example: + /// ``` + /// let agent = ureq::AgentBuilder::new() + /// .https_only(true) + /// .build(); + /// ``` + pub fn https_only(mut self, enforce: bool) -> Self { + self.config.https_only = enforce; + self + } + /// Sets the maximum number of connections allowed in the connection pool. /// By default, this is set to 100. Setting this to zero would disable /// connection pooling. diff --git a/src/error.rs b/src/error.rs index 334dce9..3fec78b 100644 --- a/src/error.rs +++ b/src/error.rs @@ -336,6 +336,8 @@ pub enum ErrorKind { UnknownScheme, /// DNS lookup failed. Dns, + /// Insecure request attempted with https only set + InsecureRequestHttpsOnly, /// Connection to server failed. ConnectionFailed, /// Too many redirects. @@ -402,6 +404,9 @@ impl fmt::Display for ErrorKind { ErrorKind::InvalidUrl => write!(f, "Bad URL"), ErrorKind::UnknownScheme => write!(f, "Unknown Scheme"), ErrorKind::Dns => write!(f, "Dns Failed"), + ErrorKind::InsecureRequestHttpsOnly => { + write!(f, "Insecure request attempted with https_only set") + } ErrorKind::ConnectionFailed => write!(f, "Connection Failed"), ErrorKind::TooManyRedirects => write!(f, "Too Many Redirects"), ErrorKind::BadStatus => write!(f, "Bad Status"), diff --git a/src/unit.rs b/src/unit.rs index b90fbc2..f2d36cd 100644 --- a/src/unit.rs +++ b/src/unit.rs @@ -348,6 +348,11 @@ fn connect_socket(unit: &Unit, hostname: &str, use_pooled: bool) -> Result<(Stre "http" | "https" | "test" => (), scheme => return Err(ErrorKind::UnknownScheme.msg(format!("unknown scheme '{}'", scheme))), }; + if unit.url.scheme() != "https" && unit.agent.config.https_only { + return Err(ErrorKind::InsecureRequestHttpsOnly.msg(format!( + "can't perform non https request with https_only set" + ))); + } if use_pooled { let pool = &unit.agent.state.pool; let proxy = &unit.agent.config.proxy;