From 4ab0320c980530bedc49cc1318bcf85c4dc28f87 Mon Sep 17 00:00:00 2001 From: Toshit Chawda Date: Sun, 13 Oct 2024 17:43:04 -0700 Subject: [PATCH] add js url support to fetch --- client/Cargo.toml | 2 +- client/demo.js | 1 + client/src/lib.rs | 37 ++++++++++++++++++++++++++++--------- client/src/websocket.rs | 6 +++--- 4 files changed, 33 insertions(+), 13 deletions(-) diff --git a/client/Cargo.toml b/client/Cargo.toml index ae3e148..772c6b0 100644 --- a/client/Cargo.toml +++ b/client/Cargo.toml @@ -30,7 +30,7 @@ tokio = "1.39.3" wasm-bindgen = "0.2.93" wasm-bindgen-futures = "0.4.43" wasm-streams = "0.4.0" -web-sys = { version = "0.3.70", features = ["BinaryType", "Headers", "MessageEvent", "Request", "RequestInit", "Response", "ResponseInit", "WebSocket"] } +web-sys = { version = "0.3.70", features = ["BinaryType", "Headers", "MessageEvent", "Request", "RequestInit", "Response", "ResponseInit", "Url", "WebSocket"] } webpki-roots = "0.26.3" wisp-mux = { path = "../wisp", features = ["wasm"], version = "5.1.0", default-features = false } diff --git a/client/demo.js b/client/demo.js index 93abdec..23ad9f4 100644 --- a/client/demo.js +++ b/client/demo.js @@ -84,6 +84,7 @@ import initEpoxy, { EpoxyClient, EpoxyClientOptions, EpoxyHandlers, info as epox for (const url of [ ["https://httpbin.org/post", { method: "POST", body: readableStream((new TextEncoder()).encode("abc")) }], ["https://httpbin.org/get", {}], + [new URL("https://httpbin.org/get"), {}], ["https://httpbin.org/gzip", {}], ["https://httpbin.org/brotli", {}], ["https://httpbin.org/redirect/11", {}], diff --git a/client/src/lib.rs b/client/src/lib.rs index 6207065..62a1ee3 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -32,7 +32,7 @@ use utils::{ }; use wasm_bindgen::prelude::*; use wasm_bindgen_futures::JsFuture; -use web_sys::{ResponseInit, WritableStream}; +use web_sys::{ResponseInit, Url, WritableStream}; #[cfg(feature = "full")] use websocket::EpoxyWebSocket; #[cfg(feature = "full")] @@ -57,10 +57,11 @@ const EPOXYCLIENT_TYPES: &'static str = r#" type EpoxyIoStream = { read: ReadableStream, write: WritableStream, -} -type EpoxyWispTransport = string | (() => { read: ReadableStream, write: WritableStream }) +}; +type EpoxyWispTransport = string | (() => { read: ReadableStream, write: WritableStream }); type EpoxyWebSocketInput = string | ArrayBuffer; -type EpoxyWebSocketHeadersInput = Headers | { [key: string]: string } +type EpoxyWebSocketHeadersInput = Headers | { [key: string]: string }; +type EpoxyUrlInput = string | URL; "#; #[wasm_bindgen] extern "C" { @@ -72,6 +73,22 @@ extern "C" { pub type EpoxyWebSocketInput; #[wasm_bindgen(typescript_type = "EpoxyWebSocketHeadersInput")] pub type EpoxyWebSocketHeadersInput; + #[wasm_bindgen(typescript_type = "EpoxyUrlInput")] + pub type EpoxyUrlInput; +} + +impl TryFrom for Uri { + type Error = EpoxyError; + fn try_from(value: EpoxyUrlInput) -> Result { + let value = JsValue::from(value); + if let Some(value) = value.dyn_ref::() { + value.href().try_into().map_err(EpoxyError::from) + } else if let Some(value) = value.as_string() { + value.try_into().map_err(EpoxyError::from) + } else { + Err(EpoxyError::InvalidUrl(format!("{:?}", value))) + } + } } type HttpBody = http_body_util::Full; @@ -129,6 +146,8 @@ pub enum EpoxyError { #[error("Invalid websocket payload: {0}")] WsInvalidPayload(String), + #[error("Invalid URL input: {0}")] + InvalidUrl(String), #[error("Invalid URL scheme: {0:?}")] InvalidUrlScheme(Option), #[error("No URL host found")] @@ -422,7 +441,7 @@ impl EpoxyClient { pub async fn connect_websocket( &self, handlers: EpoxyHandlers, - url: String, + url: EpoxyUrlInput, protocols: Vec, headers: EpoxyWebSocketHeadersInput, ) -> Result { @@ -430,7 +449,7 @@ impl EpoxyClient { } #[cfg(feature = "full")] - pub async fn connect_tcp(&self, url: String) -> Result { + pub async fn connect_tcp(&self, url: EpoxyUrlInput) -> Result { let url: Uri = url.try_into()?; let host = url.host().ok_or(EpoxyError::NoUrlHost)?; let port = url.port_u16().ok_or(EpoxyError::NoUrlPort)?; @@ -445,7 +464,7 @@ impl EpoxyClient { } #[cfg(feature = "full")] - pub async fn connect_tls(&self, url: String) -> Result { + pub async fn connect_tls(&self, url: EpoxyUrlInput) -> Result { let url: Uri = url.try_into()?; let host = url.host().ok_or(EpoxyError::NoUrlHost)?; let port = url.port_u16().ok_or(EpoxyError::NoUrlPort)?; @@ -460,7 +479,7 @@ impl EpoxyClient { } #[cfg(feature = "full")] - pub async fn connect_udp(&self, url: String) -> Result { + pub async fn connect_udp(&self, url: EpoxyUrlInput) -> Result { let url: Uri = url.try_into()?; let host = url.host().ok_or(EpoxyError::NoUrlHost)?; let port = url.port_u16().ok_or(EpoxyError::NoUrlPort)?; @@ -532,7 +551,7 @@ impl EpoxyClient { pub async fn fetch( &self, - url: String, + url: EpoxyUrlInput, options: Object, ) -> Result { let url: Uri = url.try_into()?; diff --git a/client/src/websocket.rs b/client/src/websocket.rs index 25e42d0..af271f4 100644 --- a/client/src/websocket.rs +++ b/client/src/websocket.rs @@ -24,8 +24,8 @@ use wasm_bindgen_futures::spawn_local; use crate::{ tokioio::TokioIo, utils::{entries_of_object, from_entries, ws_key}, - EpoxyClient, EpoxyError, EpoxyHandlers, EpoxyWebSocketHeadersInput, EpoxyWebSocketInput, - HttpBody, + EpoxyClient, EpoxyError, EpoxyHandlers, EpoxyUrlInput, EpoxyWebSocketHeadersInput, + EpoxyWebSocketInput, HttpBody, }; #[wasm_bindgen] @@ -39,7 +39,7 @@ impl EpoxyWebSocket { pub(crate) async fn connect( client: &EpoxyClient, handlers: EpoxyHandlers, - url: String, + url: EpoxyUrlInput, protocols: Vec, headers: EpoxyWebSocketHeadersInput, user_agent: &str,