Repository: seanmonstar/reqwest (rust)

Issue:
Regression: Error::url returns None in 0.12.16
The following code succeeds in 0.12.15, but fails in 0.12.16:

```rs
#[tokio::main]
async fn main() {
    let err = reqwest::get("https://fake.url").await.unwrap_err(); // also: http://localhost
    assert!(err.url().is_some());
}
```

I have narrowed it down to commit d9cf60e, it fails there but succeeds in the parent commit 75f62f2.

The context of this use case is a client that can connect to both a local dev server and a remote server, and displaying an error message saying to start the dev server if a connection fails to localhost in particular, rather than displaying a network error.

Pull request:
fix: request errors should include url
Closes #2740 

Patch:
diff --git a/src/async_impl/client.rs b/src/async_impl/client.rs
index 13e4c33..936bdd4 100644
--- a/src/async_impl/client.rs
+++ b/src/async_impl/client.rs
@@ -3020,7 +3020,7 @@ impl Future for PendingRequest {
                             }
                         }
 
-                        return Poll::Ready(Err(e));
+                        return Poll::Ready(Err(e.if_no_url(|| self.url.clone())));
                     }
                     Poll::Ready(Ok(res)) => res.map(super::body::boxed),
                     Poll::Pending => return Poll::Pending,
diff --git a/src/error.rs b/src/error.rs
index d67d5ce..e893be5 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -76,6 +76,13 @@ impl Error {
         self
     }
 
+    pub(crate) fn if_no_url(mut self, f: impl FnOnce() -> Url) -> Self {
+        if self.inner.url.is_none() {
+            self.inner.url = Some(f());
+        }
+        self
+    }
+
     /// Strip the related url from this error (if, for example, it contains
     /// sensitive information)
     pub fn without_url(mut self) -> Self {


Test patch:
diff --git a/tests/client.rs b/tests/client.rs
index 3ae438e..307892c 100644
--- a/tests/client.rs
+++ b/tests/client.rs
@@ -593,3 +593,10 @@ async fn http1_reason_phrase() {
         )
     );
 }
+
+#[tokio::test]
+async fn error_has_url() {
+    let u = "http://does.not.exist.local/ever";
+    let err = reqwest::get(u).await.unwrap_err();
+    assert_eq!(err.url().map(AsRef::as_ref), Some(u), "{err:?}");
+}