1use std::collections::HashMap;
2
3use lsp_core::{
10 client::Resp,
12};
13use serde::Serializer;
14use serde_json::json;
15use tracing::info;
16use wasm_bindgen::{prelude::wasm_bindgen, JsCast, JsValue};
17use web_sys::Response;
18
19#[wasm_bindgen]
20extern "C" {
21 #[wasm_bindgen(catch)]
22 async fn fetch(url: JsValue, options: JsValue) -> Result<JsValue, JsValue>;
23}
24
25pub async fn try_fetch(url: String, headers: HashMap<String, String>) -> Result<Resp, String> {
26 let ser: serde_wasm_bindgen::Serializer = serde_wasm_bindgen::Serializer::json_compatible();
41 let options_json = json!({ "headers": headers });
42 let options = ser
44 .serialize_some(&options_json)
45 .map_err(|_| String::from("failed to serialize headers"))?;
46
47 let resp_value = fetch(url.clone().into(), options)
48 .await
49 .map_err(|e| format!("{:?}", e))?;
50 info!("Got resp {}", url);
51
52 if !resp_value.is_instance_of::<Response>() {
54 return Err("Not a response!".into());
55 }
56
57 let resp: Response = resp_value.dyn_into().unwrap();
58 let status = resp.status();
59 let headers = resp.headers();
60 let headers: HashMap<String, String> =
61 serde_wasm_bindgen::from_value(headers.into()).map_err(|e| e.to_string())?;
62
63 let map: Vec<_> = headers.into_iter().map(|(k, v)| (k, v)).collect();
64
65 let body = wasm_bindgen_futures::JsFuture::from(resp.text().map_err(|e| format!("{:?}", e))?)
67 .await
68 .map_err(|e| format!("{:?}", e))?
69 .as_string()
70 .ok_or(String::from("Not a string"))?;
71
72 Ok(Resp {
73 headers: map, body,
75 status,
76 })
77}
78
79pub async fn local_fetch(
80 url: String,
81 headers: HashMap<String, String>,
82 tx: futures::channel::oneshot::Sender<Result<Resp, String>>,
83) -> Result<wasm_bindgen::JsValue, wasm_bindgen::JsValue> {
84 let resp = try_fetch(url, headers).await;
85
86 tx.send(resp).unwrap();
87
88 Ok("".into())
89}