Skip to content

Commit 65fcda7

Browse files
ranilemhueschshenekyusdacralukechu10
authored
Add gloo-net crate (#191)
* Initial commit * provide a better interface for errors, rename `RequestMethod` to `Method` * remove method for array buffer and blob in favor of as_raw * prepare for release * add CI, update readme * hide JsError in the docs * fix CI? * Install wasm-pack in CI * misc * websocket API Fixes: ranile/reqwasm#1 * add tests for websocket * update documentation, prepare for release * fix mistake in documentation * Rewrite WebSockets code (#4) * redo websockets * docs + tests * remove gloo-console * fix CI * Add getters for the underlying WebSocket fields * better API * better API part 2 electric boogaloo * deserialize Blob to Vec<u8> (#9) * Update to Rust 2021 and use JsError from gloo-utils (#10) * Update to Rust 2021 and use JsError from gloo-utils * use new toolchain * Add response.binary method to obtain response as Vec<u8> Fixes: ranile/reqwasm#7 * Remove `Clone` impl from WebSocket. When the WebSocket is used with frameworks, passed down as props, it might be `drop`ed automatically, which closes the WebSocket connection. Initially `Clone` was added so sender and receiver can be in different `spawn_local`s but it turns out that `StreamExt::split` solves that problem very well. See #13 for more information about the issue * Rustfmt + ignore editor config files * Fix onclose handling (#14) * feat: feature gate json, websocket and http; enable them by default (#16) * feat: feature gate json support * feat: feature gate weboscket api * ci: check websocket and json features seperately in CI, check no default features * feat: feature gate the http API * refactor: use futures-core and futures-sink instead of depending on whole of futures * ci: test http feature seperately in CI * fix: only compile error conversion funcs if either APIs are enabled * fix: add futures to dev-deps for tests, fix doc test * 0.3.0 * Fix outdated/missing docs * 0.3.1 * Change edition from 2021 to 2018 (#18) * Change edition from 2021 to 2018 * Fix missing import due to edition 2021 prelude * hopefully this will fix the issue (#19) * There's no message * Replace `async-broadcast` with `futures-channel::mpsc` (#21) We no longer need a multi-producer-multi-consumer channel. There's only one consumer as of ranile/reqwasm@445e9a5 * Release 0.4.0 * Fix message ordering not being preserved (#29) The websocket specification guarantees that messages are received in the same order they are sent. The implementation in this library can violate this guarantee because messages are parsed in a spawn_local block before being sent over the channel. When multiple messages are received before the next executor tick the scheduling order of the futures is unspecified. We fix this by performing all operations synchronously. The only part where async is needed is the conversion of Blob to ArrayBuffer which we obsolete by setting the websocket to always receive binary data as ArrayBuffer. * 0.4.1 * move files for gloo merge * remove licence files * gloo-specific patches * fix CI * re-export net from gloo Co-authored-by: Michael Hueschen <[email protected]> Co-authored-by: Stepan Henek <[email protected]> Co-authored-by: Yusuf Bera Ertan <[email protected]> Co-authored-by: Luke Chu <[email protected]> Co-authored-by: Valentin <[email protected]>
1 parent a46a3e5 commit 65fcda7

File tree

13 files changed

+1045
-6
lines changed

13 files changed

+1045
-6
lines changed

.github/workflows/tests.yml

+54-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ jobs:
3232
uses: actions-rs/cargo@v1
3333
with:
3434
command: test
35-
args: --all
35+
args: --workspace --exclude gloo-net
3636

3737
browser_tests:
3838
name: Browser Tests
@@ -63,6 +63,59 @@ jobs:
6363
- name: Run tests
6464
run: |
6565
for x in $(ls crates); do
66+
# gloo-net is tested separately
67+
if [[ "$x" == "net" ]]; then
68+
continue
69+
fi
6670
wasm-pack test --headless --firefox --chrome crates/$x --all-features
6771
wasm-pack test --headless --firefox --chrome crates/$x --no-default-features
6872
done
73+
74+
test-net:
75+
name: Test gloo-net
76+
runs-on: ubuntu-latest
77+
services:
78+
httpbin:
79+
image: kennethreitz/httpbin@sha256:599fe5e5073102dbb0ee3dbb65f049dab44fa9fc251f6835c9990f8fb196a72b
80+
ports:
81+
- 8080:80
82+
echo_server:
83+
image: jmalloc/echo-server@sha256:c461e7e54d947a8777413aaf9c624b4ad1f1bac5d8272475da859ae82c1abd7d
84+
ports:
85+
- 8081:8080
86+
87+
steps:
88+
- uses: actions/checkout@v2
89+
- uses: actions-rs/toolchain@v1
90+
with:
91+
toolchain: stable
92+
profile: minimal
93+
components: clippy
94+
target: wasm32-unknown-unknown
95+
96+
- name: Install wasm-pack
97+
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
98+
99+
- uses: actions/cache@v2
100+
with:
101+
path: |
102+
~/.cargo/registry
103+
~/.cargo/git
104+
target
105+
key: cargo-${{ runner.os }}-test-${{ hashFiles('**/Cargo.toml') }}
106+
restore-keys: |
107+
cargo-${{ runner.os }}-test-
108+
cargo-${{ runner.os }}-
109+
- name: Run browser tests
110+
env:
111+
HTTPBIN_URL: "http://localhost:8080"
112+
ECHO_SERVER_URL: "ws://localhost:8081"
113+
run: wasm-pack test --chrome --firefox --headless
114+
115+
- name: Run browser tests
116+
env:
117+
HTTPBIN_URL: "http://localhost:8080"
118+
ECHO_SERVER_URL: "ws://localhost:8081"
119+
uses: actions-rs/cargo@v1
120+
with:
121+
command: test

Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ gloo-console = { version = "0.2.1", path = "crates/console" }
2222
gloo-utils = { version = "0.1.1", path = "crates/utils" }
2323
gloo-history = { version = "0.1.0", path = "crates/history" }
2424
gloo-worker = { version = "0.1.0", path = "crates/worker" }
25+
gloo-net = { path = "crates/net" }
2526

2627
[features]
2728
default = []
@@ -41,4 +42,5 @@ members = [
4142
"crates/utils",
4243
"crates/history",
4344
"crates/worker",
45+
"crates/net",
4446
]

crates/net/Cargo.toml

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
[package]
2+
name = "gloo-net"
3+
version = "0.1.0"
4+
authors = ["Rust and WebAssembly Working Group", "Muhammad Hamza <[email protected]>"]
5+
edition = "2018"
6+
license = "MIT OR Apache-2.0"
7+
repository = "https://github.com/hamza1311/reqwasm"
8+
description = "HTTP requests library for WASM Apps"
9+
readme = "README.md"
10+
keywords = ["requests", "http", "wasm", "websockets"]
11+
categories = ["wasm", "web-programming::http-client", "api-bindings"]
12+
13+
[package.metadata.docs.rs]
14+
all-features = true
15+
16+
[dependencies]
17+
wasm-bindgen = "0.2"
18+
web-sys = "0.3"
19+
js-sys = "0.3"
20+
gloo-utils = { version = "0.1", path = "../utils" }
21+
22+
wasm-bindgen-futures = "0.4"
23+
futures-core = { version = "0.3", optional = true }
24+
futures-sink = { version = "0.3", optional = true }
25+
26+
thiserror = "1.0"
27+
28+
serde = { version = "1.0", features = ["derive"], optional = true }
29+
serde_json = { version = "1.0", optional = true }
30+
31+
futures-channel = { version = "0.3", optional = true }
32+
pin-project = { version = "1.0", optional = true }
33+
34+
[dev-dependencies]
35+
wasm-bindgen-test = "0.3"
36+
futures = "0.3"
37+
38+
[features]
39+
default = ["json", "websocket", "http"]
40+
41+
# Enables `.json()` on `Response`
42+
json = ["wasm-bindgen/serde-serialize", "serde", "serde_json"]
43+
# Enables the WebSocket API
44+
websocket = [
45+
'web-sys/WebSocket',
46+
'web-sys/ErrorEvent',
47+
'web-sys/FileReader',
48+
'web-sys/MessageEvent',
49+
'web-sys/ProgressEvent',
50+
'web-sys/CloseEvent',
51+
'web-sys/BinaryType',
52+
'web-sys/Blob',
53+
"futures-channel",
54+
"pin-project",
55+
"futures-core",
56+
"futures-sink",
57+
]
58+
# Enables the HTTP API
59+
http = [
60+
'web-sys/Headers',
61+
'web-sys/Request',
62+
'web-sys/RequestInit',
63+
'web-sys/RequestMode',
64+
'web-sys/Response',
65+
'web-sys/Window',
66+
'web-sys/RequestCache',
67+
'web-sys/RequestCredentials',
68+
'web-sys/ObserverCallback',
69+
'web-sys/RequestRedirect',
70+
'web-sys/ReferrerPolicy',
71+
'web-sys/AbortSignal',
72+
'web-sys/ReadableStream',
73+
'web-sys/Blob',
74+
'web-sys/FormData',
75+
]

crates/net/README.md

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<div align="center">
2+
3+
<h1><code>gloo-net</code></h1>
4+
5+
<p>
6+
<a href="https://crates.io/crates/gloo-net"><img src="https://img.shields.io/crates/v/gloo-net.svg?style=flat-square" alt="Crates.io version" /></a>
7+
<a href="https://crates.io/crates/gloo-net"><img src="https://img.shields.io/crates/d/gloo-net.svg?style=flat-square" alt="Download" /></a>
8+
<a href="https://docs.rs/gloo-net"><img src="https://img.shields.io/badge/docs-latest-blue.svg?style=flat-square" alt="docs.rs docs" /></a>
9+
</p>
10+
11+
<h3>
12+
<a href="https://docs.rs/gloo-net">API Docs</a>
13+
<span> | </span>
14+
<a href="https://github.com/rustwasm/gloo/blob/master/CONTRIBUTING.md">Contributing</a>
15+
<span> | </span>
16+
<a href="https://discordapp.com/channels/442252698964721669/443151097398296587">Chat</a>
17+
</h3>
18+
19+
<sub>Built with 🦀🕸 by <a href="https://rustwasm.github.io/">The Rust and WebAssembly Working Group</a></sub>
20+
</div>
21+
22+
HTTP requests library for WASM Apps. It provides idiomatic Rust bindings for the `web_sys` `fetch` and `WebSocket` API
23+
24+
## Examples
25+
26+
### HTTP
27+
28+
```rust
29+
let resp = Request::get("/path")
30+
.send()
31+
.await
32+
.unwrap();
33+
assert_eq!(resp.status(), 200);
34+
```
35+
36+
### WebSocket
37+
38+
```rust
39+
use reqwasm::websocket::{Message, futures::WebSocket};
40+
use wasm_bindgen_futures::spawn_local;
41+
use futures::{SinkExt, StreamExt};
42+
43+
let mut ws = WebSocket::open("wss://echo.websocket.org").unwrap();
44+
let (mut write, mut read) = ws.split();
45+
46+
spawn_local(async move {
47+
write.send(Message::Text(String::from("test"))).await.unwrap();
48+
write.send(Message::Text(String::from("test 2"))).await.unwrap();
49+
});
50+
51+
spawn_local(async move {
52+
while let Some(msg) = read.next().await {
53+
console_log!(format!("1. {:?}", msg))
54+
}
55+
console_log!("WebSocket Closed")
56+
})
57+
```

crates/net/src/error.rs

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
use gloo_utils::errors::JsError;
2+
use thiserror::Error as ThisError;
3+
4+
/// All the errors returned by this crate.
5+
#[derive(Debug, ThisError)]
6+
pub enum Error {
7+
/// Error returned by JavaScript.
8+
#[error("{0}")]
9+
JsError(JsError),
10+
/// Error returned by `serde` during deserialization.
11+
#[cfg(feature = "json")]
12+
#[cfg_attr(docsrs, doc(cfg(feature = "json")))]
13+
#[error("{0}")]
14+
SerdeError(
15+
#[source]
16+
#[from]
17+
serde_json::Error,
18+
),
19+
}
20+
21+
#[cfg(any(feature = "http", feature = "websocket"))]
22+
pub(crate) use conversion::*;
23+
#[cfg(any(feature = "http", feature = "websocket"))]
24+
mod conversion {
25+
use gloo_utils::errors::JsError;
26+
use std::convert::TryFrom;
27+
use wasm_bindgen::JsValue;
28+
29+
#[cfg(feature = "http")]
30+
pub(crate) fn js_to_error(js_value: JsValue) -> super::Error {
31+
super::Error::JsError(js_to_js_error(js_value))
32+
}
33+
34+
pub(crate) fn js_to_js_error(js_value: JsValue) -> JsError {
35+
match JsError::try_from(js_value) {
36+
Ok(error) => error,
37+
Err(_) => unreachable!("JsValue passed is not an Error type -- this is a bug"),
38+
}
39+
}
40+
}

0 commit comments

Comments
 (0)