init
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
/target
|
||||||
|
app/
|
||||||
2321
Cargo.lock
generated
Normal file
2321
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
14
Cargo.toml
Normal file
14
Cargo.toml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
[package]
|
||||||
|
name = "chat-app"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
anyhow = "1.0.98"
|
||||||
|
axum = { version = "0.8.4", features = ["multipart", "ws"] }
|
||||||
|
futures-util = "0.3.31"
|
||||||
|
serde = { version = "1.0.219", features = ["derive"] }
|
||||||
|
tokio = { version = "1.45.1", features = ["full"] }
|
||||||
|
axum-valid = { path = "../axum-valid", features = ["basic", "typed_multipart", "validify"], default-features = false }
|
||||||
|
validify = "2.0.0"
|
||||||
|
axum_typed_multipart = "0.16.2"
|
||||||
2
README.md
Normal file
2
README.md
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Frontend: SvelteKit, shadcn-svelte
|
||||||
|
Backend: axum, tokio, Websockets, sqlx, serde
|
||||||
28
src/main.rs
Normal file
28
src/main.rs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
mod send_message_handler;
|
||||||
|
mod websockets;
|
||||||
|
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use axum::{
|
||||||
|
Router,
|
||||||
|
routing::{get, post},
|
||||||
|
};
|
||||||
|
use tokio::{net::TcpListener, sync::Mutex};
|
||||||
|
|
||||||
|
pub type MyState = Arc<Mutex<Vec<String>>>;
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() -> anyhow::Result<()> {
|
||||||
|
let state = MyState::default();
|
||||||
|
|
||||||
|
let router: Router = Router::new()
|
||||||
|
.route("/message", post(send_message_handler::handler))
|
||||||
|
.route("/ws", get(websockets::websocket_handler))
|
||||||
|
.with_state(state);
|
||||||
|
|
||||||
|
let listener = TcpListener::bind("127.0.0.1:3000").await?;
|
||||||
|
|
||||||
|
let _ = axum::serve(listener, router).await;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
27
src/send_message_handler.rs
Normal file
27
src/send_message_handler.rs
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
use axum::{extract::State, http::StatusCode};
|
||||||
|
use axum_typed_multipart::{TryFromMultipart, TypedMultipart};
|
||||||
|
use axum_valid::ValidifiedByRef;
|
||||||
|
use validify::Validify;
|
||||||
|
|
||||||
|
use crate::MyState;
|
||||||
|
|
||||||
|
#[derive(Validify, TryFromMultipart)]
|
||||||
|
pub struct SendMessageData {
|
||||||
|
#[modify(trim)]
|
||||||
|
content: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn handler(
|
||||||
|
State(state): State<MyState>,
|
||||||
|
ValidifiedByRef(TypedMultipart(data)): ValidifiedByRef<TypedMultipart<SendMessageData>>,
|
||||||
|
) -> StatusCode {
|
||||||
|
let mut messages = state.lock().await;
|
||||||
|
|
||||||
|
// println!("{}", &data.content);
|
||||||
|
|
||||||
|
messages.push(data.content);
|
||||||
|
|
||||||
|
dbg!(&messages);
|
||||||
|
|
||||||
|
StatusCode::OK
|
||||||
|
}
|
||||||
42
src/websockets.rs
Normal file
42
src/websockets.rs
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use axum::{
|
||||||
|
extract::{
|
||||||
|
WebSocketUpgrade,
|
||||||
|
ws::{Message, WebSocket},
|
||||||
|
},
|
||||||
|
response::Response,
|
||||||
|
};
|
||||||
|
|
||||||
|
use futures_util::{
|
||||||
|
SinkExt as _, StreamExt,
|
||||||
|
stream::{SplitSink, SplitStream},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub async fn websocket_handler(upgrade: WebSocketUpgrade) -> Response {
|
||||||
|
upgrade.on_upgrade(handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn handler(socket: WebSocket) {
|
||||||
|
let (sender, receiver) = socket.split();
|
||||||
|
|
||||||
|
tokio::spawn(receive(receiver));
|
||||||
|
tokio::spawn(send(sender));
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn send(mut sender: SplitSink<WebSocket, Message>) {
|
||||||
|
loop {
|
||||||
|
let _ = sender.send("Hello client!".into());
|
||||||
|
tokio::time::sleep(Duration::from_secs(5)).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn receive(mut stream: SplitStream<WebSocket>) {
|
||||||
|
while let Some(Ok(message)) = stream.next().await {
|
||||||
|
let Ok(text) = message.to_text() else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
println!("Message: {text}");
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user