fix error handling

This commit is contained in:
Toshit Chawda 2024-01-10 08:40:58 -08:00
parent 81e78c89bc
commit 3b4cd96614
No known key found for this signature in database
GPG key ID: 91480ED99E2B3D9D
3 changed files with 85 additions and 48 deletions

View file

@ -4,6 +4,7 @@ mod tokioio;
mod wsstreamwrapper;
use tokioio::TokioIo;
use utils::ReplaceErr;
use wsstreamwrapper::WsStreamWrapper;
use std::sync::Arc;
@ -20,13 +21,13 @@ use web_sys::TextEncoder;
type HttpBody = http_body_util::Full<Bytes>;
async fn send_req<T>(req: http::Request<HttpBody>, io: T) -> Response<Incoming>
async fn send_req<T>(req: http::Request<HttpBody>, io: T) -> Result<Response<Incoming>, JsError>
where
T: hyper::rt::Read + hyper::rt::Write + std::marker::Unpin + 'static,
{
let (mut req_sender, conn) = hyper_conn::http1::handshake::<T, HttpBody>(io)
.await
.expect_throw("Failed to connect to host");
.replace_err("Failed to connect to host")?;
wasm_bindgen_futures::spawn_local(async move {
if let Err(e) = conn.await {
@ -38,7 +39,7 @@ where
req_sender
.send_request(req)
.await
.expect_throw("Failed to send request")
.replace_err("Failed to send request")
}
#[wasm_bindgen(start)]
@ -56,21 +57,22 @@ pub struct WsTcpWorker {
#[wasm_bindgen]
impl WsTcpWorker {
#[wasm_bindgen(constructor)]
pub async fn new(ws_url: String, useragent: String) -> Result<WsTcpWorker, JsValue> {
pub async fn new(ws_url: String, useragent: String) -> Result<WsTcpWorker, JsError> {
let ws_uri = ws_url
.parse::<uri::Uri>()
.expect_throw("Failed to parse websocket URL");
.replace_err("Failed to parse websocket url")?;
let ws_uri_scheme = ws_uri
.scheme_str()
.expect_throw("Websocket URL must have a scheme");
.replace_err("Websocket URL must have a scheme")?;
if ws_uri_scheme != "ws" && ws_uri_scheme != "wss" {
return Err("Scheme must be either `ws` or `wss`".into());
return Err(JsError::new("Scheme must be either `ws` or `wss`"));
}
debug!("connecting to ws {:?}", ws_url);
let (ws, wsmeta) = WsStreamWrapper::connect(ws_url, None)
.await
.expect_throw("Failed to connect to websocket");
.replace_err("Failed to connect to websocket")?;
debug!("connected!");
let mux = Multiplexor::new(ws, Role::Client, None, None);
@ -92,13 +94,13 @@ impl WsTcpWorker {
})
}
pub async fn fetch(&self, url: String, options: Object) -> Result<(), JsValue> {
let uri = url.parse::<uri::Uri>().expect_throw("Failed to parse URL");
let uri_scheme = uri.scheme().expect_throw("URL must have a scheme");
pub async fn fetch(&self, url: String, options: Object) -> Result<(), JsError> {
let uri = url.parse::<uri::Uri>().replace_err("Failed to parse URL")?;
let uri_scheme = uri.scheme().replace_err("URL must have a scheme")?;
if *uri_scheme != uri::Scheme::HTTP && *uri_scheme != uri::Scheme::HTTPS {
return Err("Scheme must be either `http` or `https`".into());
return Err(nerr!("Scheme must be either `http` or `https`"));
}
let uri_host = uri.host().expect_throw("URL must have a host");
let uri_host = uri.host().replace_err("URL must have a host")?;
let uri_port = if let Some(port) = uri.port() {
port.as_u16()
} else {
@ -109,7 +111,7 @@ impl WsTcpWorker {
} else if *uri_scheme == uri::Scheme::HTTPS {
443
} else {
return Err("Failed to coerce port from scheme".into());
return Err(nerr!("Failed to coerce port from scheme"));
}
};
@ -120,23 +122,24 @@ impl WsTcpWorker {
debug!("method {:?}", req_method_string);
let req_method: http::Method =
http::Method::try_from(<String as AsRef<str>>::as_ref(&req_method_string))
.expect_throw("Invalid http method");
.replace_err("Invalid http method")?;
let body: Option<Vec<u8>> = Reflect::get(&options, &JsValue::from_str("body"))
.map(|val| {
if val.is_string() {
let str = val
.as_string()
.expect_throw("Failed to encode body into uint8array");
let encoder =
TextEncoder::new().expect_throw("Failed to encode body into uint8array");
let encoded = encoder.encode_with_input(str.as_ref());
Some(encoded)
} else {
Some(Uint8Array::new(&val).to_vec())
}
})
.unwrap_or(None);
let body_jsvalue: Option<JsValue> = Reflect::get(&options, &JsValue::from_str("body")).ok();
let body = if let Some(val) = body_jsvalue {
if val.is_string() {
let str = val
.as_string()
.replace_err("Failed to get string from body")?;
let encoder =
TextEncoder::new().replace_err("Failed to create TextEncoder for body")?;
let encoded = encoder.encode_with_input(str.as_ref());
Some(encoded)
} else {
Some(Uint8Array::new(&val).to_vec())
}
} else {
None
};
let body_bytes: Bytes = match body {
Some(vec) => Bytes::from(vec),
@ -157,13 +160,13 @@ impl WsTcpWorker {
let mut builder = Request::builder().uri(uri.clone()).method(req_method);
if let Some(headers) = headers {
let headers_map = builder.headers_mut().expect_throw("failed to get headers");
let headers_map = builder.headers_mut().replace_err("Failed to get headers")?;
for hdr in headers {
headers_map.insert(
HeaderName::from_bytes(hdr[0].as_bytes())
.expect_throw("failed to get hdr name"),
.replace_err("Failed to get hdr name")?,
HeaderValue::from_str(hdr[1].clone().as_ref())
.expect_throw("failed to get hdr value"),
.replace_err("Failed to get hdr value")?,
);
}
}
@ -175,13 +178,13 @@ impl WsTcpWorker {
let request = builder
.body(HttpBody::new(body_bytes))
.expect_throw("Failed to make request");
.replace_err("Failed to make request")?;
let channel = self
.mux
.client_new_stream_channel(uri_host.as_bytes(), uri_port)
.await
.expect_throw("Failed to create multiplexor channel");
.replace_err("Failed to create multiplexor channel")?;
let mut resp: hyper::Response<Incoming>;
@ -192,20 +195,20 @@ impl WsTcpWorker {
.connect(
cloned_uri
.try_into()
.expect_throw("Failed to parse URL (rustls)"),
.replace_err("Failed to parse URL (rustls)")?,
channel,
)
.await
.expect_throw("Failed to perform TLS handshake");
resp = send_req(request, TokioIo::new(io)).await;
.replace_err("Failed to perform TLS handshake")?;
resp = send_req(request, TokioIo::new(io)).await?;
} else {
resp = send_req(request, TokioIo::new(channel)).await;
resp = send_req(request, TokioIo::new(channel)).await?;
}
log!("{:?}", resp);
let body = resp.body_mut().collect();
let body_bytes = body.await.expect_throw("Failed to get body").to_bytes();
log!("{}", std::str::from_utf8(&body_bytes).expect_throw("e"));
let body_bytes = body.await.replace_err("Failed to get body")?.to_bytes();
log!("{}", std::str::from_utf8(&body_bytes).replace_err("e")?);
Ok(())
}