Axum构建的WebSocket连接服务器失败,请求故障排查
WebSocket连接失败故障排查
问题场景
前端通过JavaScript连接Axum后端WebSocket服务时,持续报错:
WebSocket connection to 'ws://localhost:3000/message_list' failed
切换为wss协议后问题仍未解决。
后端Rust代码
use axum::{ extract::{ws::WebSocket, WebSocketUpgrade}, response::IntoResponse, routing::get, Router, }; use tokio::net::TcpListener; use tower_http::services::ServeDir; #[tokio::main] async fn main() { let listener = TcpListener::bind("localhost:3000").await.unwrap(); axum::serve(listener, router()).await.unwrap(); } fn router() -> Router { Router::new() .route("/message_list", get(hello_world)) .nest_service("/", ServeDir::new("static")) } async fn hello_world(ws: WebSocketUpgrade) -> impl IntoResponse { let _res = ws.on_upgrade(|ws| socet_handler(ws)); } async fn socet_handler(mut ws: WebSocket) { println!("IT READY!"); let _res = ws.send(axum::extract::ws::Message::Text("hi".to_string())); }
前端JS代码
let socket = new WebSocket("ws://localhost:3000/message_list")
可能的故障原因及修复方案
WebSocket握手响应未正确返回
后端hello_world函数中,调用ws.on_upgrade后未将其结果作为响应返回。Axum要求WebSocket升级处理必须返回由WebSocketUpgrade::on_upgrade生成的响应,否则前端握手请求会收到无效的HTTP响应,导致连接失败。
修正代码:async fn hello_world(ws: WebSocketUpgrade) -> impl IntoResponse { ws.on_upgrade(|ws| socet_handler(ws)) }错误使用
wss协议
后端使用普通TcpListener绑定端口,未配置TLS加密,因此wss(WebSocket over TLS)协议无法正常工作,必须使用ws协议进行连接。函数拼写失误(非连接失败直接原因,但需修正)
后端处理函数命名为socet_handler(少写一个k),虽然当前调用匹配,但属于拼写失误,建议修正为socket_handler以避免后续维护问题。忽略发送操作的错误结果
socet_handler中ws.send的返回值被直接忽略,虽然不影响连接建立,但可能导致后续消息发送失败无法被察觉,建议添加错误处理逻辑:async fn socket_handler(mut ws: WebSocket) { println!("IT READY!"); if let Err(e) = ws.send(axum::extract::ws::Message::Text("hi".to_string())).await { eprintln!("Failed to send message: {}", e); } }
内容的提问来源于stack exchange,提问作者user24168305
相关产品推荐
相关产品推荐

