{"id":18622066,"url":"https://github.com/security-union/leptos-webtransport","last_synced_at":"2025-07-12T13:06:26.718Z","repository":{"id":208878152,"uuid":"722698544","full_name":"security-union/leptos-webtransport","owner":"security-union","description":null,"archived":false,"fork":false,"pushed_at":"2024-10-27T13:53:41.000Z","size":18,"stargazers_count":6,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-07-11T07:30:31.074Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/security-union.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-11-23T18:19:03.000Z","updated_at":"2025-02-28T16:47:49.000Z","dependencies_parsed_at":"2025-04-11T12:15:37.641Z","dependency_job_id":"b0c914f6-62e4-4b43-9b67-a290d67b3e44","html_url":"https://github.com/security-union/leptos-webtransport","commit_stats":null,"previous_names":["security-union/leptos-webtransport"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/security-union/leptos-webtransport","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/security-union%2Fleptos-webtransport","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/security-union%2Fleptos-webtransport/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/security-union%2Fleptos-webtransport/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/security-union%2Fleptos-webtransport/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/security-union","download_url":"https://codeload.github.com/security-union/leptos-webtransport/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/security-union%2Fleptos-webtransport/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264995286,"owners_count":23694931,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-07T04:15:04.037Z","updated_at":"2025-07-12T13:06:26.699Z","avatar_url":"https://github.com/security-union.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Leptos WebTransport Crate\n\nWelcome to the `leptos_webtransport` crate! 🚀 This Rust crate provides WebTransport functionality for the leptos framework.\n\n## Overview\n\nWebTransport 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.\n\n## Features\n\n- **Easy Integration:** Seamlessly integrate WebTransport into your leptos-based projects.\n- **Bidirectional Communication:** Leverage the power of bidirectional communication for efficient data exchange.\n- **Multiplexed Connections:** Benefit from a single, multiplexed connection for improved performance.\n\n## Getting Started\n\nTo use `leptos_webtransport` in your project, add the following to your `Cargo.toml` file:\n\n```sh\ncargo add leptos_webtransport\n```\n\n```rust\nuse js_sys::Uint8Array;\nuse leptos::{\n    html::{Input, Textarea},\n    *,\n};\nuse leptos_webtransport::{WebTransportService, WebTransportStatus, WebTransportTask};\nuse wasm_bindgen::{JsCast, JsValue, closure::Closure};\nuse std::sync::Arc;\nuse web_sys::SubmitEvent;\n\npub const ECHO_URL: \u0026str = \"\";\n\n#[component]\npub fn WebtransportDemo() -\u003e impl IntoView {\n    let (data, set_data) = create_signal(String::new());\n    let (url, set_url) = create_signal(ECHO_URL.to_string());\n    let url_input_element: NodeRef\u003cInput\u003e = create_node_ref();\n    let (connect, set_connect) = create_signal(false);\n    let (status, set_status) = create_signal(WebTransportStatus::Closed);\n    let (transport, set_transport) = create_signal::\u003cArc\u003cOption\u003cWebTransportTask\u003e\u003e\u003e(Arc::new(None));\n    let datagrams = create_rw_signal(create_signal::\u003cVec\u003cu8\u003e\u003e(Vec::new()).0);\n    let unidirectional_streams = create_rw_signal(create_signal::\u003cOption\u003c_\u003e\u003e(None).0);\n    let bidirectional_streams = create_rw_signal(create_signal::\u003cOption\u003c_\u003e\u003e(None).0);\n    let (bidirectional_streams_from_client, set_bidirectional_streams_from_client) = create_signal::\u003cVec\u003cu8\u003e\u003e(Vec::new());\n\n    let on_submit = move |ev: SubmitEvent| {\n        ev.prevent_default();\n        let value = url_input_element()\n            .expect(\"\u003cinput\u003e to exist\")\n            .value();\n        let connected = connect.get_untracked();\n        if !connected {\n            if let Ok(t) = WebTransportService::connect(\u0026value) {\n                datagrams.set(t.datagram.clone());\n                unidirectional_streams.set(t.unidirectional_stream.clone());\n                bidirectional_streams.set(t.bidirectional_stream.clone());\n                set_status(t.status.get());\n                set_transport(Arc::new(Some(t)));\n            }\n        } else {\n            if let Some(t) = transport.get_untracked().as_ref() {\n                t.close();\n            }\n            set_status(WebTransportStatus::Closed);\n            set_transport(Arc::new(None));\n        }\n        set_connect(!connect.get_untracked());\n        set_url(value.clone());\n    };\n    let text_area_element: NodeRef\u003cTextarea\u003e = create_node_ref();\n\n    let send_data = move |ev: SubmitEvent| {\n        ev.prevent_default();\n        let value = text_area_element()\n            .expect(\"\u003ctextarea\u003e to exist\")\n            .value();\n        set_data(value.clone());\n        if let Some(t) = transport.get_untracked().as_ref() {\n            let method = ev\n                .target()\n                .expect(\"event target\")\n                .unchecked_into::\u003cweb_sys::HtmlFormElement\u003e()\n                .elements()\n                .named_item(\"method\")\n                .expect(\"method\")\n                .unchecked_into::\u003cweb_sys::HtmlInputElement\u003e()\n                .value();\n            logging::log!(\"method: {}\", method);\n\n            match method.as_str() {\n                \"send_datagram\" =\u003e {\n                    WebTransportTask::send_datagram(t.transport.clone(), value.as_bytes().to_vec());\n                }\n                \"send_undirectional_stream\" =\u003e {\n                    WebTransportTask::send_unidirectional_stream(t.transport.clone(), value.as_bytes().to_vec());\n                }\n                \"send_bidirectional_stream\" =\u003e {\n                    WebTransportTask::send_bidirectional_stream(t.transport.clone(), value.as_bytes().to_vec(), set_bidirectional_streams_from_client.clone());\n                }\n                _ =\u003e {}\n            }\n        }\n    };\n\n    create_effect(move |_| {\n        if let Some(t) = transport.get().as_ref() {\n            let status = t.status.get();\n            set_status(status.clone());\n            match status {\n                WebTransportStatus::Closed =\u003e {\n                    logging::log!(\"WebTransportStatus Connection closed\");\n                }\n                WebTransportStatus::Connecting =\u003e {\n                    logging::log!(\"WebTransportStatus Connecting...\");\n                }\n                WebTransportStatus::Opened =\u003e {\n                    logging::log!(\"WebTransportStatus Connection opened\");\n                }\n                WebTransportStatus::Error =\u003e {\n                    logging::error!(\"WebTransportStatus Connection error\");\n                }\n            }\n        }\n    });\n\n    create_effect(move |_| {\n        let datagram= datagrams.get().get();\n        let s = String::from_utf8(datagram).unwrap();\n        logging::log!(\"Received datagram: {}\", s);\n    });\n\n    create_effect(move |_| {\n        let Some(stream) = unidirectional_streams.get().get() else {\n            logging::log!(\"No unidirectional stream\");\n            return;\n        };\n        let reader = stream.get_reader().unchecked_into::\u003cweb_sys::ReadableStreamDefaultReader\u003e();\n        let c = Closure::new(|result: JsValue| {\n            let done = js_sys::Reflect::get(\u0026result, \u0026JsValue::from_str(\"done\")).unwrap().as_bool().unwrap();\n            let value = js_sys::Reflect::get(\u0026result, \u0026JsValue::from_str(\"value\")).unwrap().unchecked_into::\u003cUint8Array\u003e();\n            if done {\n                logging::log!(\"Unidirectional stream closed\");\n            }\n            let value = js_sys::Uint8Array::new(\u0026value);\n            let s = String::from_utf8(value.to_vec()).unwrap();\n            logging::log!(\"Received unidirectional stream: {}\", s);\n        });\n        let catch = Closure::new(|e: JsValue| {\n            logging::error!(\"Error reading unidirectional stream: {:?}\", e);\n        });\n        let _ = reader.read().then(\u0026c).catch(\u0026catch);\n        c.forget();\n        catch.forget();\n    });\n\n    view! {\n        \u003cform on:submit=on_submit\u003e\n            \u003cinput type=\"text\" value=url node_ref=url_input_element/\u003e\n            \u003cinput\n                type=\"submit\"\n                value=move || { if connect.get() { \"Disconnect\" } else { \"Connect\" } }\n            /\u003e\n        \u003c/form\u003e\n        \u003ch2\u003e{move || { format!(\"WebTransport Status: {:?}\", status.get()) }}\n        \u003c/h2\u003e\n        \u003cform on:submit=send_data\u003e\n            \u003ctextarea value=data node_ref=text_area_element\u003e\u003c/textarea\u003e\n            \u003cinput type=\"submit\" value=\"Send Data\"/\u003e\n            \u003cinput type=\"radio\" name=\"method\" value=\"send_datagram\" checked=true/\u003e\n            \u003clabel for=\"send_data\"\u003eSend Datagram\u003c/label\u003e\n            \u003cinput type=\"radio\" name=\"method\" value=\"send_undirectional_stream\"/\u003e\n            \u003clabel for=\"send_stream\"\u003eSend Unidirectional Stream\u003c/label\u003e\n            \u003cinput type=\"radio\" name=\"method\" value=\"send_bidirectional_stream\"/\u003e\n            \u003clabel for=\"send_datagram\"\u003eSend Bidirectional Stream\u003c/label\u003e\n        \u003c/form\u003e\n        \u003cdiv\u003e\n            \u003ch2\u003eReceived Data\u003c/h2\u003e\n            \u003cdiv\u003e\n                \u003ctextarea value=data readonly=true\u003e\u003c/textarea\u003e\n            \u003c/div\u003e\n        \u003c/div\u003e\n    }\n}\n```\n\n## Contributing\n\nWe 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.\n\n## License\n\nThis crate is distributed under the terms of the MIT license. See the [LICENSE](LICENSE) file for details.\n\nHappy coding! 🦀\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsecurity-union%2Fleptos-webtransport","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsecurity-union%2Fleptos-webtransport","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsecurity-union%2Fleptos-webtransport/lists"}