Skip to content

Commit 771a6e9

Browse files
author
Michael-F-Bryan
committed
Add more context to wasi-web errors
1 parent 5b45ab4 commit 771a6e9

File tree

1 file changed

+42
-22
lines changed

1 file changed

+42
-22
lines changed

lib/wasi-web/src/common.rs

+42-22
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::cell::Cell;
22

3+
use anyhow::Context;
34
use js_sys::Function;
45
#[allow(unused_imports, dead_code)]
56
use tracing::{debug, error, info, trace, warn};
@@ -157,48 +158,53 @@ pub async fn fetch(
157158
}
158159

159160
let request = {
160-
let request = Request::new_with_str_and_init(&url, &opts)
161-
.map_err(|_| anyhow::anyhow!("Could not construct request object"))?;
161+
let request = Request::new_with_str_and_init(url, &opts)
162+
.map_err(js_error)
163+
.context("Could not construct request object")?;
162164

163165
let set_headers = request.headers();
164166
for (name, val) in headers.iter() {
165167
let val = String::from_utf8_lossy(val.as_bytes());
166-
set_headers.set(name.as_str(), &val).map_err(|_| {
167-
anyhow::anyhow!("could not apply request header: '{name}': '{val}'")
168-
})?;
168+
set_headers
169+
.set(name.as_str(), &val)
170+
.map_err(js_error)
171+
.with_context(|| format!("could not apply request header: '{name}': '{val}'"))?;
169172
}
170173
request
171174
};
172175

173-
let resp_value = match fetch_internal(&request).await.ok() {
174-
Some(a) => a,
175-
None => {
176+
let resp_value = match fetch_internal(&request).await {
177+
Ok(a) => a,
178+
Err(e) => {
176179
// If the request failed it may be because of CORS so if a cors proxy
177180
// is configured then try again with the cors proxy
178181
let url_store;
179182
let url = if let Some(cors_proxy) = cors_proxy {
180183
url_store = format!("https://{}/{}", cors_proxy, url);
181184
url_store.as_str()
182185
} else {
183-
// TODO: more descriptive error.
184-
return Err(anyhow::anyhow!("Could not fetch '{url}'"));
186+
return Err(js_error(e).context(format!("Could not fetch '{url}'")));
185187
};
186188

187189
let request = Request::new_with_str_and_init(url, &opts)
188-
.map_err(|_| anyhow::anyhow!("Could not construct request for url '{url}'"))?;
190+
.map_err(js_error)
191+
.with_context(|| format!("Could not construct request for url '{url}'"))?;
189192

190193
let set_headers = request.headers();
191194
for (name, val) in headers.iter() {
192195
let value = String::from_utf8_lossy(val.as_bytes());
193-
set_headers.set(name.as_str(), &value).map_err(|_| {
194-
anyhow::anyhow!("Could not apply request header: '{name}': '{value}'")
195-
})?;
196+
set_headers
197+
.set(name.as_str(), &value)
198+
.map_err(js_error)
199+
.with_context(|| {
200+
anyhow::anyhow!("Could not apply request header: '{name}': '{value}'")
201+
})?;
196202
}
197203

198-
fetch_internal(&request).await.map_err(|_| {
199-
// TODO: more descriptive error.
200-
anyhow::anyhow!("Could not fetch '{url}'")
201-
})?
204+
fetch_internal(&request)
205+
.await
206+
.map_err(js_error)
207+
.with_context(|| anyhow::anyhow!("Could not fetch '{url}'"))?
202208
}
203209
};
204210
assert!(resp_value.is_instance_of::<Response>());
@@ -215,6 +221,20 @@ pub async fn fetch(
215221
Ok(resp)
216222
}
217223

224+
/// Try to extract the most appropriate error message from a [`JsValue`],
225+
/// falling back to a generic error message.
226+
fn js_error(value: JsValue) -> anyhow::Error {
227+
if let Some(e) = value.dyn_ref::<js_sys::Error>() {
228+
anyhow::Error::msg(String::from(e.message()))
229+
} else if let Some(obj) = value.dyn_ref::<js_sys::Object>() {
230+
return anyhow::Error::msg(String::from(obj.to_string()));
231+
} else if let Some(s) = value.dyn_ref::<js_sys::JsString>() {
232+
return anyhow::Error::msg(String::from(s));
233+
} else {
234+
anyhow::Error::msg("An unknown error occurred")
235+
}
236+
}
237+
218238
/*
219239
pub async fn fetch_data(
220240
url: &str,
@@ -231,10 +251,10 @@ pub async fn fetch_data(
231251
pub async fn get_response_data(resp: Response) -> Result<Vec<u8>, anyhow::Error> {
232252
let resp = { JsFuture::from(resp.array_buffer().unwrap()) };
233253

234-
let arrbuff_value = resp.await.map_err(|_| {
235-
// TODO: forward error message
236-
anyhow::anyhow!("Could not retrieve response body")
237-
})?;
254+
let arrbuff_value = resp
255+
.await
256+
.map_err(js_error)
257+
.with_context(|| format!("Could not retrieve response body"))?;
238258
assert!(arrbuff_value.is_instance_of::<js_sys::ArrayBuffer>());
239259
//let arrbuff: js_sys::ArrayBuffer = arrbuff_value.dyn_into().unwrap();
240260

0 commit comments

Comments
 (0)