https://github.com/security-union/leptos-webtransport
https://github.com/security-union/leptos-webtransport
Last synced: about 1 year ago
JSON representation
- Host: GitHub
- URL: https://github.com/security-union/leptos-webtransport
- Owner: security-union
- License: mit
- Created: 2023-11-23T18:19:03.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2024-10-27T13:53:41.000Z (over 1 year ago)
- Last Synced: 2025-07-11T07:30:31.074Z (about 1 year ago)
- Language: Rust
- Size: 17.6 KB
- Stars: 6
- Watchers: 3
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Leptos WebTransport Crate
Welcome to the `leptos_webtransport` crate! 🚀 This Rust crate provides WebTransport functionality for the leptos framework.
## Overview
WebTransport is a modern web standard that enables bidirectional communication between a client and a server over a single, multiplexed connection. This crate aims to make it easy for developers using the leptos framework to integrate and leverage WebTransport in their applications.
## Features
- **Easy Integration:** Seamlessly integrate WebTransport into your leptos-based projects.
- **Bidirectional Communication:** Leverage the power of bidirectional communication for efficient data exchange.
- **Multiplexed Connections:** Benefit from a single, multiplexed connection for improved performance.
## Getting Started
To use `leptos_webtransport` in your project, add the following to your `Cargo.toml` file:
```sh
cargo add leptos_webtransport
```
```rust
use js_sys::Uint8Array;
use leptos::{
html::{Input, Textarea},
*,
};
use leptos_webtransport::{WebTransportService, WebTransportStatus, WebTransportTask};
use wasm_bindgen::{JsCast, JsValue, closure::Closure};
use std::sync::Arc;
use web_sys::SubmitEvent;
pub const ECHO_URL: &str = "";
#[component]
pub fn WebtransportDemo() -> impl IntoView {
let (data, set_data) = create_signal(String::new());
let (url, set_url) = create_signal(ECHO_URL.to_string());
let url_input_element: NodeRef = create_node_ref();
let (connect, set_connect) = create_signal(false);
let (status, set_status) = create_signal(WebTransportStatus::Closed);
let (transport, set_transport) = create_signal::>>(Arc::new(None));
let datagrams = create_rw_signal(create_signal::>(Vec::new()).0);
let unidirectional_streams = create_rw_signal(create_signal::>(None).0);
let bidirectional_streams = create_rw_signal(create_signal::>(None).0);
let (bidirectional_streams_from_client, set_bidirectional_streams_from_client) = create_signal::>(Vec::new());
let on_submit = move |ev: SubmitEvent| {
ev.prevent_default();
let value = url_input_element()
.expect(" to exist")
.value();
let connected = connect.get_untracked();
if !connected {
if let Ok(t) = WebTransportService::connect(&value) {
datagrams.set(t.datagram.clone());
unidirectional_streams.set(t.unidirectional_stream.clone());
bidirectional_streams.set(t.bidirectional_stream.clone());
set_status(t.status.get());
set_transport(Arc::new(Some(t)));
}
} else {
if let Some(t) = transport.get_untracked().as_ref() {
t.close();
}
set_status(WebTransportStatus::Closed);
set_transport(Arc::new(None));
}
set_connect(!connect.get_untracked());
set_url(value.clone());
};
let text_area_element: NodeRef = create_node_ref();
let send_data = move |ev: SubmitEvent| {
ev.prevent_default();
let value = text_area_element()
.expect(" to exist")
.value();
set_data(value.clone());
if let Some(t) = transport.get_untracked().as_ref() {
let method = ev
.target()
.expect("event target")
.unchecked_into::()
.elements()
.named_item("method")
.expect("method")
.unchecked_into::()
.value();
logging::log!("method: {}", method);
match method.as_str() {
"send_datagram" => {
WebTransportTask::send_datagram(t.transport.clone(), value.as_bytes().to_vec());
}
"send_undirectional_stream" => {
WebTransportTask::send_unidirectional_stream(t.transport.clone(), value.as_bytes().to_vec());
}
"send_bidirectional_stream" => {
WebTransportTask::send_bidirectional_stream(t.transport.clone(), value.as_bytes().to_vec(), set_bidirectional_streams_from_client.clone());
}
_ => {}
}
}
};
create_effect(move |_| {
if let Some(t) = transport.get().as_ref() {
let status = t.status.get();
set_status(status.clone());
match status {
WebTransportStatus::Closed => {
logging::log!("WebTransportStatus Connection closed");
}
WebTransportStatus::Connecting => {
logging::log!("WebTransportStatus Connecting...");
}
WebTransportStatus::Opened => {
logging::log!("WebTransportStatus Connection opened");
}
WebTransportStatus::Error => {
logging::error!("WebTransportStatus Connection error");
}
}
}
});
create_effect(move |_| {
let datagram= datagrams.get().get();
let s = String::from_utf8(datagram).unwrap();
logging::log!("Received datagram: {}", s);
});
create_effect(move |_| {
let Some(stream) = unidirectional_streams.get().get() else {
logging::log!("No unidirectional stream");
return;
};
let reader = stream.get_reader().unchecked_into::();
let c = Closure::new(|result: JsValue| {
let done = js_sys::Reflect::get(&result, &JsValue::from_str("done")).unwrap().as_bool().unwrap();
let value = js_sys::Reflect::get(&result, &JsValue::from_str("value")).unwrap().unchecked_into::();
if done {
logging::log!("Unidirectional stream closed");
}
let value = js_sys::Uint8Array::new(&value);
let s = String::from_utf8(value.to_vec()).unwrap();
logging::log!("Received unidirectional stream: {}", s);
});
let catch = Closure::new(|e: JsValue| {
logging::error!("Error reading unidirectional stream: {:?}", e);
});
let _ = reader.read().then(&c).catch(&catch);
c.forget();
catch.forget();
});
view! {
{move || { format!("WebTransport Status: {:?}", status.get()) }}
Send Datagram
Send Unidirectional Stream
Send Bidirectional Stream
Received Data
}
}
```
## Contributing
We welcome contributions from the community! If you find a bug or have an idea for a new feature, please open an issue or submit a pull request.
## License
This crate is distributed under the terms of the MIT license. See the [LICENSE](LICENSE) file for details.
Happy coding! 🦀