Repository: seanmonstar/reqwest (language: rust)

Issue:
Classify WASM timeouts in error.is_timeout()
Can we detect the new timeout for requests in wasm like in native with `is_timeout()`? from what I see it maps the error to `Request` kind.

I am willing to open a PR to add this if needed.


Discussion / hints:
If you want to check it out, and if not, make a PR, perhaps with a test, that'd be welcome!

Fix patch:
diff --git a/src/wasm/client.rs b/src/wasm/client.rs
index c8f8106e5..f6d303e77 100644
--- a/src/wasm/client.rs
+++ b/src/wasm/client.rs
@@ -236,6 +236,13 @@ async fn fetch(req: Request) -> crate::Result<Response> {
     let p = js_fetch(&js_req);
     let js_resp = super::promise::<web_sys::Response>(p)
         .await
+        .map_err(|error| {
+            if error.to_string() == "JsValue(\"reqwest::errors::TimedOut\")" {
+                crate::error::TimedOut.into()
+            } else {
+                error
+            }
+        })
         .map_err(crate::error::request)?;
 
     // Convert from the js Response
diff --git a/src/wasm/mod.rs b/src/wasm/mod.rs
index 852bb9a6c..ea4d1ced5 100644
--- a/src/wasm/mod.rs
+++ b/src/wasm/mod.rs
@@ -63,7 +63,8 @@ impl AbortGuard {
 
     fn timeout(&mut self, timeout: Duration) {
         let ctrl = self.ctrl.clone();
-        let abort = Closure::once(move || ctrl.abort());
+        let abort =
+            Closure::once(move || ctrl.abort_with_reason(&"reqwest::errors::TimedOut".into()));
         let timeout = set_timeout(
             abort.as_ref().unchecked_ref::<js_sys::Function>(),
             timeout.as_millis().try_into().expect("timeout"),
diff --git a/src/wasm/request.rs b/src/wasm/request.rs
index 494fdcb8b..5d7ff22ea 100644
--- a/src/wasm/request.rs
+++ b/src/wasm/request.rs
@@ -119,7 +119,7 @@ impl Request {
             url: self.url.clone(),
             headers: self.headers.clone(),
             body,
-            timeout: self.timeout.clone(),
+            timeout: self.timeout,
             cors: self.cors,
             credentials: self.credentials,
         })
diff --git a/src/wasm/response.rs b/src/wasm/response.rs
index 47a90d04d..f879669ac 100644
--- a/src/wasm/response.rs
+++ b/src/wasm/response.rs
@@ -62,7 +62,7 @@ impl Response {
     ///
     /// - The server didn't send a `content-length` header.
     /// - The response is compressed and automatically decoded (thus changing
-    ///  the actual decoded length).
+    ///   the actual decoded length).
     pub fn content_length(&self) -> Option<u64> {
         self.headers()
             .get(http::header::CONTENT_LENGTH)?


Test patch:
diff --git a/tests/wasm_simple.rs b/tests/wasm_simple.rs
index 86df233d5..bd781e771 100644
--- a/tests/wasm_simple.rs
+++ b/tests/wasm_simple.rs
@@ -35,5 +35,5 @@ async fn request_with_timeout() {
         .expect_err("Expected error from aborted request");
 
     assert!(err.is_request());
-    assert!(format!("{err:?}").contains("AbortError"), "{err:?}");
+    assert!(err.is_timeout());
 }