add js url support to fetch

This commit is contained in:
Toshit Chawda 2024-10-13 17:43:04 -07:00
parent 373d2f4a4d
commit 4ab0320c98
No known key found for this signature in database
GPG key ID: 91480ED99E2B3D9D
4 changed files with 33 additions and 13 deletions

View file

@ -30,7 +30,7 @@ tokio = "1.39.3"
wasm-bindgen = "0.2.93" wasm-bindgen = "0.2.93"
wasm-bindgen-futures = "0.4.43" wasm-bindgen-futures = "0.4.43"
wasm-streams = "0.4.0" 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" webpki-roots = "0.26.3"
wisp-mux = { path = "../wisp", features = ["wasm"], version = "5.1.0", default-features = false } wisp-mux = { path = "../wisp", features = ["wasm"], version = "5.1.0", default-features = false }

View file

@ -84,6 +84,7 @@ import initEpoxy, { EpoxyClient, EpoxyClientOptions, EpoxyHandlers, info as epox
for (const url of [ for (const url of [
["https://httpbin.org/post", { method: "POST", body: readableStream((new TextEncoder()).encode("abc")) }], ["https://httpbin.org/post", { method: "POST", body: readableStream((new TextEncoder()).encode("abc")) }],
["https://httpbin.org/get", {}], ["https://httpbin.org/get", {}],
[new URL("https://httpbin.org/get"), {}],
["https://httpbin.org/gzip", {}], ["https://httpbin.org/gzip", {}],
["https://httpbin.org/brotli", {}], ["https://httpbin.org/brotli", {}],
["https://httpbin.org/redirect/11", {}], ["https://httpbin.org/redirect/11", {}],

View file

@ -32,7 +32,7 @@ use utils::{
}; };
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
use wasm_bindgen_futures::JsFuture; use wasm_bindgen_futures::JsFuture;
use web_sys::{ResponseInit, WritableStream}; use web_sys::{ResponseInit, Url, WritableStream};
#[cfg(feature = "full")] #[cfg(feature = "full")]
use websocket::EpoxyWebSocket; use websocket::EpoxyWebSocket;
#[cfg(feature = "full")] #[cfg(feature = "full")]
@ -57,10 +57,11 @@ const EPOXYCLIENT_TYPES: &'static str = r#"
type EpoxyIoStream = { type EpoxyIoStream = {
read: ReadableStream<Uint8Array>, read: ReadableStream<Uint8Array>,
write: WritableStream<Uint8Array>, write: WritableStream<Uint8Array>,
} };
type EpoxyWispTransport = string | (() => { read: ReadableStream<ArrayBuffer>, write: WritableStream<Uint8Array> }) type EpoxyWispTransport = string | (() => { read: ReadableStream<ArrayBuffer>, write: WritableStream<Uint8Array> });
type EpoxyWebSocketInput = string | ArrayBuffer; type EpoxyWebSocketInput = string | ArrayBuffer;
type EpoxyWebSocketHeadersInput = Headers | { [key: string]: string } type EpoxyWebSocketHeadersInput = Headers | { [key: string]: string };
type EpoxyUrlInput = string | URL;
"#; "#;
#[wasm_bindgen] #[wasm_bindgen]
extern "C" { extern "C" {
@ -72,6 +73,22 @@ extern "C" {
pub type EpoxyWebSocketInput; pub type EpoxyWebSocketInput;
#[wasm_bindgen(typescript_type = "EpoxyWebSocketHeadersInput")] #[wasm_bindgen(typescript_type = "EpoxyWebSocketHeadersInput")]
pub type EpoxyWebSocketHeadersInput; pub type EpoxyWebSocketHeadersInput;
#[wasm_bindgen(typescript_type = "EpoxyUrlInput")]
pub type EpoxyUrlInput;
}
impl TryFrom<EpoxyUrlInput> for Uri {
type Error = EpoxyError;
fn try_from(value: EpoxyUrlInput) -> Result<Self, Self::Error> {
let value = JsValue::from(value);
if let Some(value) = value.dyn_ref::<Url>() {
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<Bytes>; type HttpBody = http_body_util::Full<Bytes>;
@ -129,6 +146,8 @@ pub enum EpoxyError {
#[error("Invalid websocket payload: {0}")] #[error("Invalid websocket payload: {0}")]
WsInvalidPayload(String), WsInvalidPayload(String),
#[error("Invalid URL input: {0}")]
InvalidUrl(String),
#[error("Invalid URL scheme: {0:?}")] #[error("Invalid URL scheme: {0:?}")]
InvalidUrlScheme(Option<String>), InvalidUrlScheme(Option<String>),
#[error("No URL host found")] #[error("No URL host found")]
@ -422,7 +441,7 @@ impl EpoxyClient {
pub async fn connect_websocket( pub async fn connect_websocket(
&self, &self,
handlers: EpoxyHandlers, handlers: EpoxyHandlers,
url: String, url: EpoxyUrlInput,
protocols: Vec<String>, protocols: Vec<String>,
headers: EpoxyWebSocketHeadersInput, headers: EpoxyWebSocketHeadersInput,
) -> Result<EpoxyWebSocket, EpoxyError> { ) -> Result<EpoxyWebSocket, EpoxyError> {
@ -430,7 +449,7 @@ impl EpoxyClient {
} }
#[cfg(feature = "full")] #[cfg(feature = "full")]
pub async fn connect_tcp(&self, url: String) -> Result<EpoxyIoStream, EpoxyError> { pub async fn connect_tcp(&self, url: EpoxyUrlInput) -> Result<EpoxyIoStream, EpoxyError> {
let url: Uri = url.try_into()?; let url: Uri = url.try_into()?;
let host = url.host().ok_or(EpoxyError::NoUrlHost)?; let host = url.host().ok_or(EpoxyError::NoUrlHost)?;
let port = url.port_u16().ok_or(EpoxyError::NoUrlPort)?; let port = url.port_u16().ok_or(EpoxyError::NoUrlPort)?;
@ -445,7 +464,7 @@ impl EpoxyClient {
} }
#[cfg(feature = "full")] #[cfg(feature = "full")]
pub async fn connect_tls(&self, url: String) -> Result<EpoxyIoStream, EpoxyError> { pub async fn connect_tls(&self, url: EpoxyUrlInput) -> Result<EpoxyIoStream, EpoxyError> {
let url: Uri = url.try_into()?; let url: Uri = url.try_into()?;
let host = url.host().ok_or(EpoxyError::NoUrlHost)?; let host = url.host().ok_or(EpoxyError::NoUrlHost)?;
let port = url.port_u16().ok_or(EpoxyError::NoUrlPort)?; let port = url.port_u16().ok_or(EpoxyError::NoUrlPort)?;
@ -460,7 +479,7 @@ impl EpoxyClient {
} }
#[cfg(feature = "full")] #[cfg(feature = "full")]
pub async fn connect_udp(&self, url: String) -> Result<EpoxyIoStream, EpoxyError> { pub async fn connect_udp(&self, url: EpoxyUrlInput) -> Result<EpoxyIoStream, EpoxyError> {
let url: Uri = url.try_into()?; let url: Uri = url.try_into()?;
let host = url.host().ok_or(EpoxyError::NoUrlHost)?; let host = url.host().ok_or(EpoxyError::NoUrlHost)?;
let port = url.port_u16().ok_or(EpoxyError::NoUrlPort)?; let port = url.port_u16().ok_or(EpoxyError::NoUrlPort)?;
@ -532,7 +551,7 @@ impl EpoxyClient {
pub async fn fetch( pub async fn fetch(
&self, &self,
url: String, url: EpoxyUrlInput,
options: Object, options: Object,
) -> Result<web_sys::Response, EpoxyError> { ) -> Result<web_sys::Response, EpoxyError> {
let url: Uri = url.try_into()?; let url: Uri = url.try_into()?;

View file

@ -24,8 +24,8 @@ use wasm_bindgen_futures::spawn_local;
use crate::{ use crate::{
tokioio::TokioIo, tokioio::TokioIo,
utils::{entries_of_object, from_entries, ws_key}, utils::{entries_of_object, from_entries, ws_key},
EpoxyClient, EpoxyError, EpoxyHandlers, EpoxyWebSocketHeadersInput, EpoxyWebSocketInput, EpoxyClient, EpoxyError, EpoxyHandlers, EpoxyUrlInput, EpoxyWebSocketHeadersInput,
HttpBody, EpoxyWebSocketInput, HttpBody,
}; };
#[wasm_bindgen] #[wasm_bindgen]
@ -39,7 +39,7 @@ impl EpoxyWebSocket {
pub(crate) async fn connect( pub(crate) async fn connect(
client: &EpoxyClient, client: &EpoxyClient,
handlers: EpoxyHandlers, handlers: EpoxyHandlers,
url: String, url: EpoxyUrlInput,
protocols: Vec<String>, protocols: Vec<String>,
headers: EpoxyWebSocketHeadersInput, headers: EpoxyWebSocketHeadersInput,
user_agent: &str, user_agent: &str,