mirror of
https://github.com/MercuryWorkshop/epoxy-tls.git
synced 2025-05-12 14:00:01 -04:00
remove non esmodules builds, use a js snippet
This commit is contained in:
parent
1a01197764
commit
98526aa347
8 changed files with 154 additions and 160 deletions
13
Cargo.lock
generated
13
Cargo.lock
generated
|
@ -227,12 +227,6 @@ version = "0.21.7"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.22.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
|
@ -512,7 +506,6 @@ version = "2.1.0"
|
|||
dependencies = [
|
||||
"async-compression",
|
||||
"async-trait",
|
||||
"base64 0.22.1",
|
||||
"bytes",
|
||||
"cfg-if",
|
||||
"event-listener",
|
||||
|
@ -591,7 +584,7 @@ name = "fastwebsockets"
|
|||
version = "0.8.0"
|
||||
source = "git+https://github.com/r58Playz/fastwebsockets#9152ec2e28512feeb93d3aba3b516f07355025b6"
|
||||
dependencies = [
|
||||
"base64 0.21.7",
|
||||
"base64",
|
||||
"bytes",
|
||||
"http-body-util",
|
||||
"hyper 1.4.1",
|
||||
|
@ -840,7 +833,7 @@ version = "7.5.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "765c9198f173dd59ce26ff9f95ef0aafd0a0fe01fb9d72841bc5066a4c06511d"
|
||||
dependencies = [
|
||||
"base64 0.21.7",
|
||||
"base64",
|
||||
"byteorder",
|
||||
"flate2",
|
||||
"nom",
|
||||
|
@ -1811,7 +1804,7 @@ dependencies = [
|
|||
"async-stream",
|
||||
"async-trait",
|
||||
"axum",
|
||||
"base64 0.21.7",
|
||||
"base64",
|
||||
"bytes",
|
||||
"h2 0.3.26",
|
||||
"http 0.2.12",
|
||||
|
|
|
@ -9,7 +9,6 @@ crate-type = ["cdylib"]
|
|||
[dependencies]
|
||||
async-compression = { version = "0.4.11", features = ["futures-io", "gzip", "brotli"], optional = true }
|
||||
async-trait = "0.1.80"
|
||||
base64 = { version = "0.22.1", optional = true }
|
||||
bytes = "1.6.0"
|
||||
cfg-if = "1.0.0"
|
||||
event-listener = "5.3.1"
|
||||
|
@ -17,7 +16,6 @@ fastwebsockets = { version = "0.8.0", features = ["unstable-split"], optional =
|
|||
flume = "0.11.0"
|
||||
futures-rustls = { version = "0.26.0", default-features = false, features = ["tls12", "ring"] }
|
||||
futures-util = { version = "0.3.30", features = ["sink"] }
|
||||
getrandom = { version = "0.2.15", features = ["js", "std"], optional = true }
|
||||
http = "1.1.0"
|
||||
http-body-util = "0.1.2"
|
||||
hyper = "1.3.1"
|
||||
|
@ -35,6 +33,10 @@ web-sys = { version = "0.3.69", features = ["BinaryType", "Headers", "MessageEve
|
|||
webpki-roots = "0.26.3"
|
||||
wisp-mux = { path = "../wisp", features = ["wasm"] }
|
||||
|
||||
[dependencies.getrandom]
|
||||
version = "*"
|
||||
features = ["js"]
|
||||
|
||||
[dependencies.ring]
|
||||
version = "*"
|
||||
features = ["wasm32_unknown_unknown_js"]
|
||||
|
@ -49,5 +51,5 @@ features = ["nightly"]
|
|||
|
||||
[features]
|
||||
default = ["full"]
|
||||
full = ["fastwebsockets", "base64", "async-compression", "getrandom", "hyper-util-wasm/http2"]
|
||||
full = ["fastwebsockets", "async-compression", "hyper-util-wasm/http2"]
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ mkdir pkg/
|
|||
|
||||
RUSTFLAGS='-C target-feature=+atomics,+bulk-memory -Zlocation-detail=none' cargo build --target wasm32-unknown-unknown -Z build-std=panic_abort,std -Z build-std-features=panic_immediate_abort,optimize_for_size --release "$@"
|
||||
echo "[epx] cargo finished"
|
||||
wasm-bindgen --weak-refs --target no-modules --no-modules-global epoxy --out-dir out/ ../target/wasm32-unknown-unknown/release/epoxy_client.wasm
|
||||
wasm-bindgen --target web --out-dir out/ ../target/wasm32-unknown-unknown/release/epoxy_client.wasm
|
||||
echo "[epx] wasm-bindgen finished"
|
||||
|
||||
if ! [ "${RELEASE:-0}" = "1" ]; then
|
||||
|
@ -21,7 +21,21 @@ mv out/epoxy_client_bg.wasm out/epoxy_client_unoptimized.wasm
|
|||
time wasm-opt $WASMOPTFLAGS -Oz --vacuum --dce --enable-threads --enable-bulk-memory out/epoxy_client_unoptimized.wasm -o out/epoxy_client_bg.wasm
|
||||
echo "[epx] wasm-opt finished"
|
||||
|
||||
# === js ===
|
||||
|
||||
AUTOGENERATED_SOURCE=$(<"out/epoxy_client.js")
|
||||
|
||||
AUTOGENERATED_SNIPPET_PATH=$(<"out/epoxy_client.js")
|
||||
# remove everything before the snippet path quote (which is the first quote in the file)
|
||||
AUTOGENERATED_SNIPPET_PATH=${AUTOGENERATED_SNIPPET_PATH#*$'\''}
|
||||
# remove everything after the snippet path quote (which is the second quote in the file)
|
||||
AUTOGENERATED_SNIPPET_PATH=${AUTOGENERATED_SNIPPET_PATH%%$'\''*}
|
||||
|
||||
# replace a dot at the start of the var with out
|
||||
AUTOGENERATED_SNIPPET=$(base64 -w0 ${AUTOGENERATED_SNIPPET_PATH/#./out})
|
||||
|
||||
AUTOGENERATED_SOURCE=${AUTOGENERATED_SOURCE//${AUTOGENERATED_SNIPPET_PATH}/data:application/javascript$';'base64,${AUTOGENERATED_SNIPPET}}
|
||||
|
||||
# patch for websocket sharedarraybuffer error
|
||||
AUTOGENERATED_SOURCE=${AUTOGENERATED_SOURCE//getObject(arg0).send(getArrayU8FromWasm0(arg1, arg2)/getObject(arg0).send(new Uint8Array(getArrayU8FromWasm0(arg1, arg2)).buffer}
|
||||
# patch for safari OOM errors on safari iOS 16/older devices
|
||||
|
@ -29,32 +43,36 @@ AUTOGENERATED_SOURCE=${AUTOGENERATED_SOURCE//getObject(arg0).send(getArrayU8From
|
|||
AUTOGENERATED_SOURCE=${AUTOGENERATED_SOURCE//maximum:16384,shared:true/maximum:/iPad|iPhone|iPod/.test(navigator.userAgent)?4096:8192,shared:true}
|
||||
# patch to set proper wasm path
|
||||
AUTOGENERATED_SOURCE=${AUTOGENERATED_SOURCE//'_bg.wasm'/'.wasm'}
|
||||
echo "$AUTOGENERATED_SOURCE" > pkg/epoxy.js
|
||||
AUTOGENERATED_SOURCE=${AUTOGENERATED_SOURCE//'epoxy_client.wasm'/'epoxy.wasm'}
|
||||
|
||||
cp pkg/epoxy.js pkg/epoxy-module.js
|
||||
echo "export default epoxy;" >> pkg/epoxy-module.js
|
||||
# delete initSync export
|
||||
AUTOGENERATED_SOURCE=${AUTOGENERATED_SOURCE//export $'{' initSync $'}\n'/}
|
||||
|
||||
# don't export internals
|
||||
AUTOGENERATED_SOURCE=${AUTOGENERATED_SOURCE//return __wbg_finalize_init/__wbg_finalize_init}
|
||||
|
||||
echo "$AUTOGENERATED_SOURCE" > pkg/epoxy.js
|
||||
|
||||
WASM_BASE64=$(base64 -w0 out/epoxy_client_bg.wasm)
|
||||
AUTOGENERATED_SOURCE=${AUTOGENERATED_SOURCE//__wbg_init(input, maybe_memory) \{/__wbg_init(maybe_memory) \{$'\n'let input=\'data:application/wasm;base64,$WASM_BASE64\'}
|
||||
AUTOGENERATED_SOURCE=${AUTOGENERATED_SOURCE//return __wbg_finalize_init(instance, module);/__wbg_finalize_init(instance, module);$'\n'return epoxy;}
|
||||
AUTOGENERATED_SOURCE=${AUTOGENERATED_SOURCE//if (wasm !== undefined) return wasm;/if (wasm !== undefined) return epoxy;}
|
||||
|
||||
echo "$AUTOGENERATED_SOURCE" > pkg/epoxy-bundled.js
|
||||
|
||||
cp pkg/epoxy-bundled.js pkg/epoxy-module-bundled.js
|
||||
echo "export default epoxy;" >> pkg/epoxy-module-bundled.js
|
||||
# === types ===
|
||||
|
||||
AUTOGENERATED_TYPEDEFS=$(<"out/epoxy_client.d.ts")
|
||||
AUTOGENERATED_TYPEDEFS=${AUTOGENERATED_TYPEDEFS%%export class IntoUnderlyingByteSource*}
|
||||
echo "$AUTOGENERATED_TYPEDEFS" > pkg/epoxy-module.d.ts
|
||||
echo -e "}\ndeclare type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;" >> pkg/epoxy-module.d.ts
|
||||
echo -e "export default function epoxy(module_or_path?: InitInput | Promise<InitInput>, maybe_memory?: WebAssembly.Memory): Promise<typeof wasm_bindgen>;" >> pkg/epoxy-module.d.ts
|
||||
echo "$AUTOGENERATED_TYPEDEFS" > pkg/epoxy-module-bundled.d.ts
|
||||
echo -e "}\nexport default function epoxy(maybe_memory?: WebAssembly.Memory): Promise<typeof wasm_bindgen>;" >> pkg/epoxy-module-bundled.d.ts
|
||||
echo "$AUTOGENERATED_TYPEDEFS" > pkg/epoxy-bundled.d.ts
|
||||
echo -e "}\ndeclare function epoxy(maybe_memory?: WebAssembly.Memory): Promise<typeof wasm_bindgen>;" >> pkg/epoxy-bundled.d.ts
|
||||
AUTOGENERATED_TYPES=$(<"out/epoxy_client.d.ts")
|
||||
|
||||
AUTOGENERATED_TYPES=${AUTOGENERATED_TYPES//$'\n'export interface InitOutput*InitOutput;$'\n'/}
|
||||
AUTOGENERATED_TYPES=${AUTOGENERATED_TYPES//Promise<InitOutput>/Promise<void>}
|
||||
|
||||
echo "$AUTOGENERATED_TYPES" > pkg/epoxy.d.ts
|
||||
|
||||
# remove useless comment
|
||||
AUTOGENERATED_TYPES=${AUTOGENERATED_TYPES//$'\n*' If $'`'module_or_path*$'}' module_or_path/}
|
||||
AUTOGENERATED_TYPES=${AUTOGENERATED_TYPES//module_or_path*, /}
|
||||
|
||||
echo "$AUTOGENERATED_TYPES" > pkg/epoxy-bundled.d.ts
|
||||
|
||||
cp out/epoxy_client.d.ts pkg/epoxy.d.ts
|
||||
cp out/epoxy_client_bg.wasm pkg/epoxy.wasm
|
||||
|
||||
rm -r out/
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import epoxyModule from "./pkg/epoxy-module-bundled.js";
|
||||
import initEpoxy, { EpoxyClient, EpoxyClientOptions, EpoxyHandlers } from "./pkg/epoxy-bundled.js";
|
||||
|
||||
(async () => {
|
||||
const params = (new URL(location.href)).searchParams;
|
||||
|
@ -25,15 +25,7 @@ import epoxyModule from "./pkg/epoxy-module-bundled.js";
|
|||
window.scrollTo(0, document.body.scrollHeight);
|
||||
}
|
||||
|
||||
const plog = (str) => {
|
||||
console.log(str);
|
||||
}
|
||||
|
||||
const epoxy = await epoxyModule();
|
||||
const EpoxyClientOptions = epoxy.EpoxyClientOptions;
|
||||
const EpoxyClient = epoxy.EpoxyClient;
|
||||
const EpoxyHandlers = epoxy.EpoxyHandlers;
|
||||
|
||||
await initEpoxy();
|
||||
let epoxy_client_options = new EpoxyClientOptions();
|
||||
epoxy_client_options.user_agent = navigator.userAgent;
|
||||
|
||||
|
@ -234,7 +226,7 @@ import epoxyModule from "./pkg/epoxy-module-bundled.js";
|
|||
while (true) {
|
||||
log("sending `data`");
|
||||
await ws.send("data");
|
||||
await (new Promise((res, _) => setTimeout(res, 10)));
|
||||
await (new Promise((res, _) => setTimeout(res, 100)));
|
||||
}
|
||||
} else if (should_reconnect_test) {
|
||||
while (true) {
|
||||
|
|
|
@ -21,28 +21,28 @@
|
|||
"license": "AGPL-3.0-only",
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./full/epoxy-module-bundled.js",
|
||||
"types": "./full/epoxy-module-bundled.d.ts"
|
||||
"import": "./full/epoxy-bundled.js",
|
||||
"types": "./full/epoxy-bundled.d.ts"
|
||||
},
|
||||
"./epoxy": {
|
||||
"import": "./full/epoxy-module.js",
|
||||
"types": "./full/epoxy-module.d.ts"
|
||||
"import": "./full/epoxy.js",
|
||||
"types": "./full/epoxy.d.ts"
|
||||
},
|
||||
"./epoxy-bundled": {
|
||||
"import": "./full/epoxy-module-bundled.js",
|
||||
"types": "./full/epoxy-module-bundled.d.ts"
|
||||
"import": "./full/epoxy-bundled.js",
|
||||
"types": "./full/epoxy-bundled.d.ts"
|
||||
},
|
||||
"./minimal-epoxy": {
|
||||
"import": "./minimal/epoxy-module.js",
|
||||
"types": "./minimal/epoxy-module.d.ts"
|
||||
"import": "./minimal/epoxy.js",
|
||||
"types": "./minimal/epoxy.d.ts"
|
||||
},
|
||||
"./minimal-epoxy-bundled": {
|
||||
"import": "./minimal/epoxy-module-bundled.js",
|
||||
"types": "./minimal/epoxy-module-bundled.d.ts"
|
||||
"import": "./minimal/epoxy-bundled.js",
|
||||
"types": "./minimal/epoxy-bundled.d.ts"
|
||||
}
|
||||
},
|
||||
"browser": "./full/epoxy-module-bundled.js",
|
||||
"module": "./full/epoxy-module-bundled.js",
|
||||
"main": "./full/epoxy-module-bundled.js",
|
||||
"types": "./full/epoxy-module-bundled.d.ts"
|
||||
"browser": "./full/epoxy-bundled.js",
|
||||
"module": "./full/epoxy-bundled.js",
|
||||
"main": "./full/epoxy-bundled.js",
|
||||
"types": "./full/epoxy-bundled.d.ts"
|
||||
}
|
||||
|
|
|
@ -18,12 +18,12 @@ use hyper::{body::Incoming, Uri};
|
|||
use hyper_util_wasm::client::legacy::Client;
|
||||
#[cfg(feature = "full")]
|
||||
use io_stream::{EpoxyIoStream, EpoxyUdpStream};
|
||||
use js_sys::{Array, Function, Object, Reflect};
|
||||
use js_sys::{Array, Function, Object};
|
||||
use stream_provider::{StreamProvider, StreamProviderService};
|
||||
use thiserror::Error;
|
||||
use utils::{
|
||||
asyncread_to_readablestream_stream, convert_body, entries_of_object, is_null_body, is_redirect,
|
||||
object_get, object_set, IncomingBody, UriExt, WasmExecutor,
|
||||
object_get, object_set, object_truthy, IncomingBody, UriExt, WasmExecutor,
|
||||
};
|
||||
use wasm_bindgen::prelude::*;
|
||||
use wasm_streams::ReadableStream;
|
||||
|
@ -97,10 +97,6 @@ pub enum EpoxyError {
|
|||
ResponseHeadersFromEntriesFailed,
|
||||
#[error("Failed to construct response object")]
|
||||
ResponseNewFailed,
|
||||
#[error("Failed to construct define_property object")]
|
||||
DefinePropertyObjFailed,
|
||||
#[error("Failed to set raw header item")]
|
||||
RawHeaderSetFailed,
|
||||
}
|
||||
|
||||
impl From<EpoxyError> for JsValue {
|
||||
|
@ -222,10 +218,7 @@ pub struct EpoxyClient {
|
|||
#[wasm_bindgen]
|
||||
impl EpoxyClient {
|
||||
#[wasm_bindgen(constructor)]
|
||||
pub fn new(
|
||||
wisp_url: String,
|
||||
options: EpoxyClientOptions,
|
||||
) -> Result<EpoxyClient, EpoxyError> {
|
||||
pub fn new(wisp_url: String, options: EpoxyClientOptions) -> Result<EpoxyClient, EpoxyError> {
|
||||
let wisp_url: Uri = wisp_url.try_into()?;
|
||||
if wisp_url.scheme_str() != Some("wss") && wisp_url.scheme_str() != Some("ws") {
|
||||
return Err(EpoxyError::InvalidUrlScheme);
|
||||
|
@ -406,32 +399,31 @@ impl EpoxyClient {
|
|||
let host = url.host().ok_or(EpoxyError::NoUrlHost)?;
|
||||
|
||||
let request_method = object_get(&options, "method")
|
||||
.and_then(|x| x.as_string())
|
||||
.as_string()
|
||||
.unwrap_or_else(|| "GET".to_string());
|
||||
let request_method: Method = Method::from_str(&request_method)?;
|
||||
|
||||
let request_redirect = object_get(&options, "redirect")
|
||||
.map(|x| {
|
||||
!matches!(
|
||||
x.as_string().unwrap_or_default().as_str(),
|
||||
"error" | "manual"
|
||||
)
|
||||
})
|
||||
.unwrap_or(true);
|
||||
let request_redirect = !matches!(
|
||||
object_get(&options, "redirect")
|
||||
.as_string()
|
||||
.unwrap_or_default()
|
||||
.as_str(),
|
||||
"error" | "manual"
|
||||
);
|
||||
|
||||
let mut body_content_type: Option<String> = None;
|
||||
let body = match object_get(&options, "body") {
|
||||
let body = match object_truthy(object_get(&options, "body")) {
|
||||
Some(buf) => {
|
||||
let (body, req) = convert_body(buf)
|
||||
let (body, content_type) = convert_body(buf)
|
||||
.await
|
||||
.map_err(|_| EpoxyError::InvalidRequestBody)?;
|
||||
body_content_type = req.headers().get("Content-Type").ok().flatten();
|
||||
body_content_type = content_type;
|
||||
Bytes::from(body.to_vec())
|
||||
}
|
||||
None => Bytes::new(),
|
||||
};
|
||||
|
||||
let headers = object_get(&options, "headers").and_then(|val| {
|
||||
let headers = object_truthy(object_get(&options, "headers")).and_then(|val| {
|
||||
if web_sys::Headers::instanceof(&val) {
|
||||
Some(entries_of_object(&Object::from_entries(&val).ok()?))
|
||||
} else if val.is_truthy() {
|
||||
|
@ -548,42 +540,25 @@ impl EpoxyClient {
|
|||
)
|
||||
.map_err(|_| EpoxyError::ResponseNewFailed)?;
|
||||
|
||||
Object::define_property(
|
||||
&resp,
|
||||
&"url".into(),
|
||||
&utils::define_property_obj(response_uri.to_string().into(), false)
|
||||
.map_err(|_| EpoxyError::DefinePropertyObjFailed)?,
|
||||
);
|
||||
|
||||
Object::define_property(
|
||||
&resp,
|
||||
&"redirected".into(),
|
||||
&utils::define_property_obj(redirected.into(), false)
|
||||
.map_err(|_| EpoxyError::DefinePropertyObjFailed)?,
|
||||
);
|
||||
utils::define_property(&resp, "url", response_uri.to_string().into());
|
||||
utils::define_property(&resp, "redirected", redirected.into());
|
||||
|
||||
let raw_headers = Object::new();
|
||||
for (k, v) in response_headers_raw.iter() {
|
||||
let k: JsValue = k.to_string().into();
|
||||
let k = k.as_str();
|
||||
let v: JsValue = v.to_str()?.to_string().into();
|
||||
if let Ok(jv) = Reflect::get(&raw_headers, &k) {
|
||||
if jv.is_array() {
|
||||
let arr = Array::from(&jv);
|
||||
arr.push(&v);
|
||||
object_set(&raw_headers, &k, &arr)?;
|
||||
} else if jv.is_truthy() {
|
||||
object_set(&raw_headers, &k, &Array::of2(&jv, &v))?;
|
||||
} else {
|
||||
object_set(&raw_headers, &k, &v)?;
|
||||
}
|
||||
let jv = object_get(&raw_headers, k);
|
||||
if jv.is_array() {
|
||||
let arr = Array::from(&jv);
|
||||
arr.push(&v);
|
||||
object_set(&raw_headers, &k, arr.into());
|
||||
} else if jv.is_truthy() {
|
||||
object_set(&raw_headers, &k, Array::of2(&jv, &v).into());
|
||||
} else {
|
||||
object_set(&raw_headers, &k, v);
|
||||
}
|
||||
}
|
||||
Object::define_property(
|
||||
&resp,
|
||||
&"rawHeaders".into(),
|
||||
&utils::define_property_obj(raw_headers.into(), false)
|
||||
.map_err(|_| EpoxyError::DefinePropertyObjFailed)?,
|
||||
);
|
||||
utils::define_property(&resp, "rawHeaders", raw_headers.into());
|
||||
|
||||
Ok(resp)
|
||||
}
|
||||
|
|
|
@ -7,10 +7,9 @@ use bytes::{buf::UninitSlice, BufMut, Bytes, BytesMut};
|
|||
use futures_util::{ready, AsyncRead, Future, Stream, TryStreamExt};
|
||||
use http::{HeaderValue, Uri};
|
||||
use hyper::{body::Body, rt::Executor};
|
||||
use js_sys::{Array, ArrayBuffer, Object, Reflect, Uint8Array};
|
||||
use js_sys::{Array, JsString, Object, Uint8Array};
|
||||
use pin_project_lite::pin_project;
|
||||
use wasm_bindgen::{prelude::*, JsCast, JsValue};
|
||||
use wasm_bindgen_futures::JsFuture;
|
||||
|
||||
use crate::EpoxyError;
|
||||
|
||||
|
@ -177,54 +176,65 @@ pub fn is_null_body(code: u16) -> bool {
|
|||
[101, 204, 205, 304].contains(&code)
|
||||
}
|
||||
|
||||
pub fn object_get(obj: &Object, key: &str) -> Option<JsValue> {
|
||||
Reflect::get(obj, &key.into()).ok()
|
||||
}
|
||||
|
||||
pub fn object_set(obj: &Object, key: &JsValue, value: &JsValue) -> Result<(), EpoxyError> {
|
||||
if Reflect::set(obj, key, value).map_err(|_| EpoxyError::RawHeaderSetFailed)? {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(EpoxyError::RawHeaderSetFailed)
|
||||
#[wasm_bindgen(inline_js = r#"
|
||||
export function object_get(obj, k) {
|
||||
try {
|
||||
return obj[k]
|
||||
} catch {
|
||||
return undefined
|
||||
}
|
||||
};
|
||||
export function object_set(obj, k, v) {
|
||||
try { obj[k] = v } catch {}
|
||||
};
|
||||
|
||||
export async function convert_body_inner(body) {
|
||||
let req = new Request("", { method: "POST", duplex: "half", body });
|
||||
let type = req.headers.get("content-type");
|
||||
return [new Uint8Array(await req.arrayBuffer()), type];
|
||||
}
|
||||
|
||||
pub async fn convert_body(val: JsValue) -> Result<(Uint8Array, web_sys::Request), JsValue> {
|
||||
let mut request_init = web_sys::RequestInit::new();
|
||||
request_init.method("POST").body(Some(&val));
|
||||
object_set(&request_init, &"duplex".into(), &"half".into())?;
|
||||
let req = web_sys::Request::new_with_str_and_init("/", &request_init)?;
|
||||
Ok((
|
||||
JsFuture::from(req.array_buffer()?)
|
||||
.await?
|
||||
.dyn_into::<ArrayBuffer>()
|
||||
.map(|x| Uint8Array::new(&x))?,
|
||||
req,
|
||||
))
|
||||
export function entries_of_object_inner(obj) {
|
||||
Object.entries(obj).map(x => x.map(String))
|
||||
}
|
||||
|
||||
export function define_property(obj, k, v) {
|
||||
Object.defineProperty(obj, k, { value: v, writable: false });
|
||||
}
|
||||
|
||||
export function ws_key() {
|
||||
let key = new Uint8Array(16);
|
||||
crypto.getRandomValues(key);
|
||||
return btoa(Array.from(key).map(String.fromCharCode).join(''));
|
||||
}
|
||||
"#)]
|
||||
extern "C" {
|
||||
pub fn object_get(obj: &Object, key: &str) -> JsValue;
|
||||
pub fn object_set(obj: &Object, key: &str, val: JsValue);
|
||||
|
||||
#[wasm_bindgen(catch)]
|
||||
async fn convert_body_inner(val: JsValue) -> Result<JsValue, JsValue>;
|
||||
|
||||
fn entries_of_object_inner(obj: &Object) -> Vec<Array>;
|
||||
pub fn define_property(obj: &Object, key: &str, val: JsValue);
|
||||
pub fn ws_key() -> String;
|
||||
}
|
||||
|
||||
pub async fn convert_body(val: JsValue) -> Result<(Uint8Array, Option<String>), JsValue> {
|
||||
let req: Array = convert_body_inner(val).await?.unchecked_into();
|
||||
let str: Option<JsString> = object_truthy(req.at(1)).map(|x| x.unchecked_into());
|
||||
Ok((req.at(0).unchecked_into(), str.map(Into::into)))
|
||||
}
|
||||
|
||||
pub fn entries_of_object(obj: &Object) -> Vec<Vec<String>> {
|
||||
Object::entries(obj)
|
||||
.to_vec()
|
||||
.iter()
|
||||
.filter_map(|val| {
|
||||
Array::from(val)
|
||||
.to_vec()
|
||||
.iter()
|
||||
.map(|val| val.as_string())
|
||||
.collect::<Option<Vec<_>>>()
|
||||
entries_of_object_inner(obj)
|
||||
.into_iter()
|
||||
.map(|x| {
|
||||
x.iter()
|
||||
.map(|x| x.unchecked_into::<JsString>().into())
|
||||
.collect()
|
||||
})
|
||||
.collect::<Vec<Vec<_>>>()
|
||||
}
|
||||
|
||||
pub fn define_property_obj(value: JsValue, writable: bool) -> Result<Object, JsValue> {
|
||||
let entries: Array = [
|
||||
Array::of2(&"value".into(), &value),
|
||||
Array::of2(&"writable".into(), &writable.into()),
|
||||
]
|
||||
.iter()
|
||||
.collect::<Array>();
|
||||
Object::from_entries(&entries)
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn asyncread_to_readablestream_stream<R: AsyncRead>(
|
||||
|
@ -234,3 +244,11 @@ pub fn asyncread_to_readablestream_stream<R: AsyncRead>(
|
|||
.map_ok(|x| Uint8Array::from(x.as_ref()).into())
|
||||
.map_err(|x| EpoxyError::from(x).into())
|
||||
}
|
||||
|
||||
pub fn object_truthy(val: JsValue) -> Option<JsValue> {
|
||||
if val.is_truthy() {
|
||||
Some(val)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
use std::{str::from_utf8, sync::Arc};
|
||||
|
||||
use base64::{prelude::BASE64_STANDARD, Engine};
|
||||
use bytes::Bytes;
|
||||
use fastwebsockets::{
|
||||
FragmentCollectorRead, Frame, OpCode, Payload, Role, WebSocket, WebSocketWrite,
|
||||
};
|
||||
use futures_util::lock::Mutex;
|
||||
use getrandom::getrandom;
|
||||
use http::{
|
||||
header::{
|
||||
CONNECTION, HOST, SEC_WEBSOCKET_KEY, SEC_WEBSOCKET_PROTOCOL, SEC_WEBSOCKET_VERSION,
|
||||
|
@ -24,7 +22,9 @@ use wasm_bindgen::{prelude::*, JsError, JsValue};
|
|||
use wasm_bindgen_futures::spawn_local;
|
||||
|
||||
use crate::{
|
||||
tokioio::TokioIo, utils::entries_of_object, EpoxyClient, EpoxyError, EpoxyHandlers, HttpBody,
|
||||
tokioio::TokioIo,
|
||||
utils::{entries_of_object, ws_key},
|
||||
EpoxyClient, EpoxyError, EpoxyHandlers, HttpBody,
|
||||
};
|
||||
|
||||
#[wasm_bindgen]
|
||||
|
@ -54,17 +54,13 @@ impl EpoxyWebSocket {
|
|||
let url: Uri = url.try_into()?;
|
||||
let host = url.host().ok_or(EpoxyError::NoUrlHost)?;
|
||||
|
||||
let mut rand = [0u8; 16];
|
||||
getrandom(&mut rand)?;
|
||||
let key = BASE64_STANDARD.encode(rand);
|
||||
|
||||
let mut request = Request::builder()
|
||||
.method(Method::GET)
|
||||
.uri(url.clone())
|
||||
.header(HOST, host)
|
||||
.header(CONNECTION, "upgrade")
|
||||
.header(UPGRADE, "websocket")
|
||||
.header(SEC_WEBSOCKET_KEY, key)
|
||||
.header(SEC_WEBSOCKET_KEY, ws_key())
|
||||
.header(SEC_WEBSOCKET_VERSION, "13")
|
||||
.header(USER_AGENT, user_agent);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue