first commit
This commit is contained in:
108
src/main.rs
Normal file
108
src/main.rs
Normal file
@@ -0,0 +1,108 @@
|
||||
use futures_util::{SinkExt, StreamExt};
|
||||
use poem::{
|
||||
get, handler,
|
||||
listener::TcpListener,
|
||||
web::{
|
||||
websocket::{Message, WebSocket},
|
||||
Data, Html, Path,
|
||||
},
|
||||
EndpointExt, IntoResponse, Route, Server,
|
||||
};
|
||||
|
||||
#[handler]
|
||||
fn index() -> Html<&'static str> {
|
||||
Html(
|
||||
r###"
|
||||
<body>
|
||||
<form id="loginForm">
|
||||
Name: <input id="nameInput" type="text" />
|
||||
<button type="submit">Login</button>
|
||||
</form>
|
||||
|
||||
<form id="sendForm" hidden>
|
||||
Text: <input id="msgInput" type="text" />
|
||||
<button type="submit">Send</button>
|
||||
</form>
|
||||
|
||||
<textarea id="msgsArea" cols="50" rows="30" hidden></textarea>
|
||||
</body>
|
||||
<script>
|
||||
let ws;
|
||||
const loginForm = document.querySelector("#loginForm");
|
||||
const sendForm = document.querySelector("#sendForm");
|
||||
const nameInput = document.querySelector("#nameInput");
|
||||
const msgInput = document.querySelector("#msgInput");
|
||||
const msgsArea = document.querySelector("#msgsArea");
|
||||
|
||||
nameInput.focus();
|
||||
|
||||
loginForm.addEventListener("submit", function(event) {
|
||||
event.preventDefault();
|
||||
loginForm.hidden = true;
|
||||
sendForm.hidden = false;
|
||||
msgsArea.hidden = false;
|
||||
msgInput.focus();
|
||||
ws = new WebSocket("ws://127.0.0.1:3000/ws/" + nameInput.value);
|
||||
ws.onmessage = function(event) {
|
||||
msgsArea.value += event.data + "\r\n";
|
||||
}
|
||||
});
|
||||
|
||||
sendForm.addEventListener("submit", function(event) {
|
||||
event.preventDefault();
|
||||
ws.send(msgInput.value);
|
||||
msgInput.value = "";
|
||||
});
|
||||
|
||||
</script>
|
||||
"###,
|
||||
)
|
||||
}
|
||||
|
||||
#[handler]
|
||||
fn ws(
|
||||
Path(name): Path<String>,
|
||||
ws: WebSocket,
|
||||
sender: Data<&tokio::sync::broadcast::Sender<String>>,
|
||||
) -> impl IntoResponse {
|
||||
let sender = sender.clone();
|
||||
let mut receiver = sender.subscribe();
|
||||
ws.on_upgrade(move |socket| async move {
|
||||
let (mut sink, mut stream) = socket.split();
|
||||
|
||||
tokio::spawn(async move {
|
||||
while let Some(Ok(msg)) = stream.next().await {
|
||||
if let Message::Text(text) = msg {
|
||||
if sender.send(format!("{name}: {text}")).is_err() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
tokio::spawn(async move {
|
||||
while let Ok(msg) = receiver.recv().await {
|
||||
if sink.send(Message::Text(msg)).await.is_err() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), std::io::Error> {
|
||||
if std::env::var_os("RUST_LOG").is_none() {
|
||||
std::env::set_var("RUST_LOG", "poem=debug");
|
||||
}
|
||||
tracing_subscriber::fmt::init();
|
||||
|
||||
let app = Route::new().at("/", get(index)).at(
|
||||
"/ws/:name",
|
||||
get(ws.data(tokio::sync::broadcast::channel::<String>(32).0)),
|
||||
);
|
||||
|
||||
Server::new(TcpListener::bind("127.0.0.1:3000"))
|
||||
.run(app)
|
||||
.await
|
||||
}
|
||||
Reference in New Issue
Block a user