This commit is contained in:
2026-06-20 16:44:40 +02:00
parent 4466b6c1ca
commit e38dcfca5a
9 changed files with 310 additions and 25 deletions
+121
View File
@@ -0,0 +1,121 @@
use crate::auth::token::verify_jwt;
use crate::core::AppState;
use crate::http::context::CurrentUser;
use crate::models::user::Model as User;
use crate::routes::gateway::GatewayClient;
use axum::{
extract::{
ws::{Message, WebSocket, WebSocketUpgrade}, Query,
State,
},
response::IntoResponse,
};
use futures_util::{sink::SinkExt, stream::StreamExt};
use serde::Deserialize;
use tokio::sync::mpsc;
use uuid::Uuid;
#[derive(Deserialize)]
pub struct WsQuery {
token: String,
}
pub async fn ws_handler(
Query(query): Query<WsQuery>,
ws: WebSocketUpgrade,
State(state): State<AppState>,
CurrentUser(user): CurrentUser,
) -> impl IntoResponse {
ws.on_upgrade(move |socket| handle_socket(socket, state, user))
// let token = query.token;
// Vérification du JWT
// match verify_jwt(&token, &state.config.jwt.secret) {
// Ok(claims) => ws.on_upgrade(move |socket| handle_socket(socket, state, claims.user_id)),
// Err(e) => {
// tracing::error!("WS auth error: {:?}", e);
// (axum::http::StatusCode::UNAUTHORIZED, "Invalid token").into_response()
// }
// }
}
async fn handle_socket(socket: WebSocket, state: AppState, user: User) {
let (mut sender, mut receiver) = socket.split();
let (tx, mut rx) = mpsc::unbounded_channel();
let event_bus = state.event_bus.clone();
let client = GatewayClient::new(user);
client.on_connect().await;
state.gateway.add_user(client);
// // Enregistrement du client (Connect)
// on_connect(user_id, tx, &state).await;
//
// // Task pour envoyer les messages du canal mpsc vers le WebSocket
// let mut send_task = tokio::spawn(async move {
// while let Some(message) = rx.recv().await {
// if sender.send(message).await.is_err() {
// break;
// }
// }
// });
//
// // Task pour recevoir les messages du WebSocket
// let state_clone = state.clone();
// let mut recv_task = tokio::spawn(async move {
// while let Some(Ok(message)) = receiver.next().await {
// on_message(user_id, message, &state_clone).await;
// }
// });
//
// // Attente de la fin d'une des tâches (déconnexion)
// tokio::select! {
// _ = (&mut send_task) => recv_task.abort(),
// _ = (&mut recv_task) => send_task.abort(),
// };
//
// // Déconnexion (Disconnect)
// on_disconnect(user_id, &state).await;
}
pub async fn on_connect(user_id: Uuid, tx: mpsc::UnboundedSender<Message>, state: &AppState) {
tracing::info!("Client connected: {}", user_id);
let mut clients = state
.gateway
.clients
.write()
.expect("Failed to lock clients for writing");
clients.insert(user_id, GatewayClient { user_id, tx });
}
pub async fn on_disconnect(user_id: Uuid, state: &AppState) {
tracing::info!("Client disconnected: {}", user_id);
let mut clients = state
.gateway
.clients
.write()
.expect("Failed to lock clients for writing");
clients.remove(&user_id);
}
pub async fn on_message(user_id: Uuid, message: Message, _state: &AppState) {
tracing::debug!("Message received from {}: {:?}", user_id, message);
// Exemple d'utilisation de l'état/repositories
// let user_opt = state.repositories.user.get_by_id(user_id).await.ok().flatten();
match message {
Message::Text(text) => {
tracing::info!("Received text from {}: {}", user_id, text);
// Logique de dispatch ou de traitement ici
}
Message::Binary(_) => {
tracing::info!("Received binary from {}", user_id);
}
Message::Close(_) => {
tracing::info!("Received close from {}", user_id);
}
_ => {}
}
}