Repository: seanmonstar/reqwest (language: rust)

Issue:
`https_only` is not enforced after following a redirect
Minimal repro:
```
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = reqwest::ClientBuilder::new().https_only(true).build().unwrap();
    let resp = client.get("https://nghttp2.org/httpbin/redirect-to?url=http://httpbin.org/get")
        .send()
        .await?
        .text()
        .await?;
    println!("{:#?}", resp);
    Ok(())
}
```


Discussion / hints:

Fix patch:
diff --git a/src/async_impl/client.rs b/src/async_impl/client.rs
index e069a686b..2e88c0e81 100644
--- a/src/async_impl/client.rs
+++ b/src/async_impl/client.rs
@@ -1634,8 +1634,15 @@ impl Future for PendingRequest {
                     match action {
                         redirect::ActionKind::Follow => {
                             debug!("redirecting '{}' to '{}'", self.url, loc);
-                            self.url = loc;
 
+                            if self.client.https_only && loc.scheme() != "https" {
+                                return Poll::Ready(Err(error::redirect(
+                                    error::url_bad_scheme(loc.clone()),
+                                    loc,
+                                )));
+                            }
+
+                            self.url = loc;
                             let mut headers =
                                 std::mem::replace(self.as_mut().headers(), HeaderMap::new());
 


Test patch:
diff --git a/tests/redirect.rs b/tests/redirect.rs
index 16f7712f5..5124b4a27 100644
--- a/tests/redirect.rs
+++ b/tests/redirect.rs
@@ -316,3 +316,31 @@ async fn test_redirect_302_with_set_cookies() {
     assert_eq!(res.url().as_str(), dst);
     assert_eq!(res.status(), reqwest::StatusCode::OK);
 }
+
+#[cfg(feature = "__rustls")]
+#[tokio::test]
+#[ignore = "Needs TLS support in the test server"]
+async fn test_redirect_https_only_enforced_gh1312() {
+    let server = server::http(move |_req| async move {
+        http::Response::builder()
+            .status(302)
+            .header("location", "http://insecure")
+            .body(Default::default())
+            .unwrap()
+    });
+
+    let url = format!("https://{}/yikes", server.addr());
+
+    let res = reqwest::Client::builder()
+        .danger_accept_invalid_certs(true)
+        .use_rustls_tls()
+        .https_only(true)
+        .build()
+        .expect("client builder")
+        .get(&url)
+        .send()
+        .await;
+
+    let err = res.unwrap_err();
+    assert!(err.is_redirect());
+}