Repository: seanmonstar/reqwest (language: rust)

Issue:
Requests always time out on Windows 10
I tried running the following code with both Rust Stable and Nightly:  
```rust
#![deny(warnings)]

//! `cargo run --example simple`

extern crate reqwest;

fn main() -> Result<(), Box<std::error::Error>> {

    println!("GET https://www.rust-lang.org");

    let mut res = reqwest::get("https://www.rust-lang.org/en-US/")?;

    println!("Status: {}", res.status());
    println!("Headers:\n{:?}", res.headers());

    // copy the response body directly to stdout
    std::io::copy(&mut res, &mut std::io::stdout())?;

    println!("\n\nDone.");
    Ok(())
}
```

With either toolchain, I get the following output:  
```
GET https://www.rust-lang.org
Error: Error { kind: Io(Custom { kind: TimedOut, error: StringError("timed out") }), url: Some("https://www.rust-lang.org/en-US/") }
error: process didn't exit successfully: `target\debug\tersttt.exe` (exit code: 1)
```


Discussion / hints:
What version of reqwest was used?
I seem to have the same problem. I'm using version `0.9.7` and getting timeouts on both `nightly-x86_64-pc-windows-msvc` and `nightly-x86_64-pc-windows-gnu`. The same code works on my other Linux machine.
Would you be able to try an `http` address as well? Just curious if its the DNS or TLS refactor that is bugged.
Seems to be a regression from `0.9.5` to `0.9.6`. Setting `reqwest = "=0.9.5"` in the Cargo.toml fixes the problem. The problem also occurs with a `http` address.
Also occurs with `http` addresses for me as well. Using `0.9.7` as well.
Just tested if `0.9.5` works for me and it does (after a `cargo clean`)!
Would either of you be able to tell me if 0.9.5 works even if its hyper dependency is at 0.12.20?
The problem is trust-dns.

```
INFO C:\Users\Arnavion\.cargo\registry\src\github.com-1ecc6299db9ec823\trust-dns-proto-0.6.1\src\xfer\dns_exchange.rs:122 sending message via: UDP([fec0:0:0:ffff::3]:53)
INFO C:\Users\Arnavion\.cargo\registry\src\github.com-1ecc6299db9ec823\trust-dns-proto-0.6.1\src\xfer\dns_exchange.rs:122 sending message via: UDP([fec0:0:0:ffff::2]:53)
INFO C:\Users\Arnavion\.cargo\registry\src\github.com-1ecc6299db9ec823\trust-dns-proto-0.6.1\src\xfer\dns_exchange.rs:122 sending message via: UDP([fec0:0:0:ffff::1]:53)
INFO C:\Users\Arnavion\.cargo\registry\src\github.com-1ecc6299db9ec823\trust-dns-proto-0.6.1\src\xfer\dns_exchange.rs:122 sending message via: UDP([fec0:0:0:ffff::3]:53)
INFO C:\Users\Arnavion\.cargo\registry\src\github.com-1ecc6299db9ec823\trust-dns-proto-0.6.1\src\xfer\dns_exchange.rs:122 sending message via: UDP([fec0:0:0:ffff::2]:53)
INFO C:\Users\Arnavion\.cargo\registry\src\github.com-1ecc6299db9ec823\trust-dns-proto-0.6.1\src\xfer\dns_exchange.rs:122 sending message via: UDP([fec0:0:0:ffff::1]:53)
Error: https://www.google.com: timed out
```

This is on Windows 7. I don't have IPv6 on my network.

Relevant crate versions:

- reqwest 0.9.7
- trust-dns-proto 0.6.1
- trust-dns-resolver 0.10.2
In https://github.com/bluejekyll/trust-dns/blob/master/crates/resolver/src/system_conf/windows.rs#L22 it enumerates every adapter, even ones that don't make sense. I have VirtualBox which has an adapter for its VMs ("VirtualBox Host-Only Network"), which does have IPv6 enabled, so it ends up picking the resolver for that and trying to use it. Disabling IPv6 on that adapter fixed the problem.

@CoolOppo @Bobo1239 Is it the same for you?
I just put in config to disable trust-dns on Android, we can also add in Windows, and file an issue upstream.
Can confirm that the problem doesn't occur when disabling the other adapters.
So it seems the problem may not happen to everyone, just systems that have a lot of adapters, or adapters that don't work?

Still, it's not difficult to add Windows to the Android conditional configs.
Yes, I think disabling it on Windows is a good idea until trust-dns gets a fix. Either it needs to ignore the nameservers from these adapters, or it needs to query them in parallel, or it needs to have a shorter timeout that doesn't elapse before it's tried every nameserver, or whatever.

It's not really about "a lot of adapters" or "adapters that don't work". Having adapters that don't have an internet connection is quite normal. VM software like Hyper-V and VirtualBox, VPN software, etc all add virtual adapters. These adapters *work*, and `getaddrinfo` already knows about which adapter's nameservers it's supposed to use. But trust-dns goes behind the OS's back to make its own list of nameservers and gets confused by it.

Especially in the VPN case, I imagine it'll also end up leaking internal domain names over the public internet where gai would've resolved them by the VPN network's DNS server.
There's currently one primary contributor to trust-dns for Windows. If you would care to move this discussion to bluejekyll/trust-dns#605 and help us come up with some potential fixes, that would be greatly appreciated.

Fix patch:
diff --git a/Cargo.toml b/Cargo.toml
index 0a0425d36..a750d379e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -38,7 +38,7 @@ tokio-rustls = { version = "0.8", optional = true }
 webpki-roots = { version = "0.15", optional = true }
 rustls = { version = "0.14", features = ["dangerous_configuration"], optional = true }
 
-[target.'cfg(not(target_os = "android"))'.dependencies]
+[target.'cfg(not(any(target_os = "android", windows)))'.dependencies]
 trust-dns-resolver = "0.10"
 
 [dev-dependencies]
diff --git a/src/connect.rs b/src/connect.rs
index a979a8545..48c26e1c5 100644
--- a/src/connect.rs
+++ b/src/connect.rs
@@ -13,13 +13,13 @@ use bytes::BufMut;
 use std::io;
 use std::sync::Arc;
 
-#[cfg(not(target_os = "android"))]
+#[cfg(not(any(target_os = "android", windows)))]
 use dns::TrustDnsResolver;
 use Proxy;
 
-#[cfg(not(target_os = "android"))]
+#[cfg(not(any(target_os = "android", windows)))]
 type HttpConnector = ::hyper::client::HttpConnector<TrustDnsResolver>;
-#[cfg(target_os = "android")]
+#[cfg(any(target_os = "android", windows))]
 type HttpConnector = ::hyper::client::HttpConnector;
 
 
@@ -74,14 +74,14 @@ impl Connector {
     }
 }
 
-#[cfg(not(target_os = "android"))]
+#[cfg(not(any(target_os = "android", windows)))]
 fn http_connector() -> ::Result<HttpConnector> {
     TrustDnsResolver::new()
         .map(HttpConnector::new_with_resolver)
         .map_err(::error::dns_system_conf)
 }
 
-#[cfg(target_os = "android")]
+#[cfg(any(target_os = "android", windows))]
 fn http_connector() -> ::Result<HttpConnector> {
     Ok(HttpConnector::new(4))
 }
diff --git a/src/error.rs b/src/error.rs
index af4a1bd9a..7107ef4c0 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -140,6 +140,7 @@ impl Error {
             Kind::NativeTls(ref e) => Some(e),
             #[cfg(feature = "rustls-tls")]
             Kind::Rustls(ref e) => Some(e),
+            #[cfg(not(any(target_os = "android", windows)))]
             Kind::DnsSystemConf(ref e) => Some(e),
             Kind::Io(ref e) => Some(e),
             Kind::UrlEncoded(ref e) => Some(e),
@@ -238,6 +239,7 @@ impl fmt::Display for Error {
             Kind::NativeTls(ref e) => fmt::Display::fmt(e, f),
             #[cfg(feature = "rustls-tls")]
             Kind::Rustls(ref e) => fmt::Display::fmt(e, f),
+            #[cfg(not(any(target_os = "android", windows)))]
             Kind::DnsSystemConf(ref e) => {
                 write!(f, "failed to load DNS system conf: {}", e)
             },
@@ -272,6 +274,7 @@ impl StdError for Error {
             Kind::NativeTls(ref e) => e.description(),
             #[cfg(feature = "rustls-tls")]
             Kind::Rustls(ref e) => e.description(),
+            #[cfg(not(any(target_os = "android", windows)))]
             Kind::DnsSystemConf(_) => "failed to load DNS system conf",
             Kind::Io(ref e) => e.description(),
             Kind::UrlEncoded(ref e) => e.description(),
@@ -296,6 +299,7 @@ impl StdError for Error {
             Kind::NativeTls(ref e) => e.cause(),
             #[cfg(feature = "rustls-tls")]
             Kind::Rustls(ref e) => e.cause(),
+            #[cfg(not(any(target_os = "android", windows)))]
             Kind::DnsSystemConf(ref e) => e.cause(),
             Kind::Io(ref e) => e.cause(),
             Kind::UrlEncoded(ref e) => e.cause(),
@@ -322,6 +326,7 @@ pub(crate) enum Kind {
     NativeTls(::native_tls::Error),
     #[cfg(feature = "rustls-tls")]
     Rustls(::rustls::TLSError),
+    #[cfg(not(any(target_os = "android", windows)))]
     DnsSystemConf(io::Error),
     Io(io::Error),
     UrlEncoded(::serde_urlencoded::ser::Error),
@@ -496,6 +501,7 @@ pub(crate) fn url_bad_scheme(url: Url) -> Error {
     Error::new(Kind::UrlBadScheme, Some(url))
 }
 
+#[cfg(not(any(target_os = "android", windows)))]
 pub(crate) fn dns_system_conf(io: io::Error) -> Error {
     Error::new(Kind::DnsSystemConf(io), None)
 }
diff --git a/src/lib.rs b/src/lib.rs
index f779ac10c..107d3eb12 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -196,7 +196,7 @@ extern crate serde_urlencoded;
 extern crate tokio;
 #[cfg_attr(feature = "default-tls", macro_use)]
 extern crate tokio_io;
-#[cfg(not(target_os = "android"))]
+#[cfg(not(any(target_os = "android", windows)))]
 extern crate trust_dns_resolver;
 extern crate url;
 extern crate uuid;
@@ -238,7 +238,7 @@ mod connect;
 mod connect_async;
 mod body;
 mod client;
-#[cfg(not(target_os = "android"))]
+#[cfg(not(any(target_os = "android", windows)))]
 mod dns;
 mod into_url;
 mod proxy;


Test patch: