//websocket路由
func add_router(method_type string, path string, handler http.HandlerFunc) rest.Route {
return rest.Route{
Method: method_type,
Path: types.Admin_Http_URL_Prefix + path,
Handler: handler,
}
}
func Router() (r []rest.Route) {
login_chk := services.NewLogin()
r = []rest.Route{
add_router(types.GET,"/ws/",WsChat),
}
controller.go
func WsChat(w http.ResponseWriter, r *http.Request) {
var (
conn *websocket.Conn
err error
)
//先进行登录身份校验,获取当前用户id,昵称基础信息
authorization := (*r).Header.Get("authorization")
if len(authorization) < 1{
fmt.Printf("错误\n")
http.Error(w, "token校验失败", http.StatusInternalServerError)
return
}
}
//我在建立一个websocket的连接,在建立之前需要对header头的authorization进行,如果不合法则返回错误消息,但在浏览器访问前端页面,没有任何输出,怎么能输出错误呢?
前端页面:
<!DOCTYPE html>
<html>
<head>
<title>go websocket</title>
<meta charset="utf-8" />
</head>
<body>
<script type="text/javascript">
var wsUri ="ws://192.168.5.17:33121/api/dd/ws";
var output;
function init() {
output = document.getElementById("output");
testWebSocket();
}
function testWebSocket() {
websocket = new WebSocket(wsUri);
websocket.onopen = function(evt) {
onOpen(evt)
};
websocket.onclose = function(evt) {
onClose(evt)
};
websocket.onmessage = function(evt) {
onMessage(evt)
};
websocket.onerror = function(evt) {
onError(evt)
};
}
function onOpen(evt) {
writeToScreen("CONNECTED");
// doSend("WebSocket rocks");
}
function onClose(evt) {
writeToScreen("DISCONNECTED");
}
function onMessage(evt) {
writeToScreen('<span style="color: blue;">RESPONSE: '+ evt.data+'</span>');
// websocket.close();
}
function onError(evt) {
writeToScreen('<span style="color: red;">ERROR:</span> '+ evt.data);
}
function doSend(message) {
writeToScreen("SENT: " + message);
websocket.send(message);
}
function writeToScreen(message) {
var pre = document.createElement("p");
pre.style.wordWrap = "break-word";
pre.innerHTML = message;
output.appendChild(pre);
}
window.addEventListener("load", init, false);
function sendBtnClick(){
var msg = document.getElementById("input").value;
doSend(msg);
document.getElementById("input").value = '';
}
function closeBtnClick(){
websocket.close();
}
</script>
<h2>WebSocket Test</h2>
<input type="text" id="input"></input>
<button onclick="sendBtnClick()" >send</button>
<button onclick="closeBtnClick()" >close</button>
<div id="output"></div>
</body>
</html>
golang websocket返回http错误码
- 写回答
- 好问题 0 提建议
- 关注问题
- 邀请回答
-
4条回答 默认 最新
关注让【宝码香车】来帮您解答,本回答参考DeepSeek编写,并整理提供。
如果答案让您满意,请采纳、点赞、关注,非常感谢!
.
每日一句正能量,让它带给您好心情:努力的意义,在于当机会来临时,你有能力抓住它。
.Golang WebSocket 返回 HTTP 错误码的解决方案
在您的代码中,当 WebSocket 连接的身份校验失败时,您使用了
http.Error返回错误,但这在 WebSocket 连接中无法被前端正确捕获。以下是解决方案:问题分析
当 WebSocket 握手阶段返回 HTTP 错误码时,浏览器会触发
onerror事件,但evt.data通常为空。您需要修改后端代码以正确返回 WebSocket 握手错误。后端修改
func WsChat(w http.ResponseWriter, r *http.Request) { // 先进行登录身份校验 authorization := r.Header.Get("Authorization") if len(authorization) < 1 { // WebSocket 握手失败时返回 401 状态码 w.WriteHeader(http.StatusUnauthorized) w.Write([]byte("token校验失败")) return } // 身份验证通过,升级为 WebSocket 连接 upgrader := websocket.Upgrader{ CheckOrigin: func(r *http.Request) bool { return true // 在生产环境中应该检查来源 }, } conn, err := upgrader.Upgrade(w, r, nil) if err != nil { log.Printf("WebSocket upgrade failed: %v", err) return } defer conn.Close() // 处理 WebSocket 连接 for { messageType, message, err := conn.ReadMessage() if err != nil { log.Printf("Read error: %v", err) break } // 处理消息 err = conn.WriteMessage(messageType, message) if err != nil { log.Printf("Write error: %v", err) break } } }前端修改
function onError(evt) { writeToScreen('<span style="color: red;">ERROR:</span> WebSocket连接失败'); // 可以在这里添加更详细的错误处理 console.error('WebSocket error:', evt); } function testWebSocket() { websocket = new WebSocket(wsUri); // 添加认证头信息 websocket.onopen = function(evt) { onOpen(evt); }; websocket.onclose = function(evt) { // 根据关闭代码判断是否为认证失败 if (evt.code === 1008 || evt.code === 4000) { writeToScreen('<span style="color: red;">认证失败:</span> ' + evt.reason); } else { writeToScreen("DISCONNECTED"); } }; websocket.onmessage = function(evt) { onMessage(evt); }; websocket.onerror = function(evt) { onError(evt); }; }完整的改进方案
后端完整代码
import ( "net/http" "github.com/gorilla/websocket" ) var upgrader = websocket.Upgrader{ CheckOrigin: func(r *http.Request) bool { return true // 生产环境应根据需要配置 }, } func WsChat(w http.ResponseWriter, r *http.Request) { // 身份验证 if !authenticate(r) { http.Error(w, "Unauthorized", http.StatusUnauthorized) return } conn, err := upgrader.Upgrade(w, r, nil) if err != nil { log.Printf("WebSocket upgrade failed: %v", err) return } defer conn.Close() // WebSocket 通信逻辑 handleWebSocketConnection(conn) } func authenticate(r *http.Request) bool { authorization := r.Header.Get("Authorization") return len(authorization) > 0 // 这里应该实现实际的认证逻辑 } func handleWebSocketConnection(conn *websocket.Conn) { for { messageType, message, err := conn.ReadMessage() if err != nil { if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) { log.Printf("WebSocket error: %v", err) } break } // 处理接收到的消息 processMessage(conn, messageType, message) } } func processMessage(conn *websocket.Conn, messageType int, message []byte) { // 这里实现您的业务逻辑 err := conn.WriteMessage(messageType, message) if err != nil { log.Printf("Write error: %v", err) } }前端完整代码
<!DOCTYPE html> <html> <head> <title>go websocket</title> <meta charset="utf-8" /> </head> <body> <script type="text/javascript"> var wsUri = "ws://192.168.5.17:33121/api/dd/ws"; var output; var websocket; function init() { output = document.getElementById("output"); testWebSocket(); } function testWebSocket() { websocket = new WebSocket(wsUri); websocket.onopen = function(evt) { onOpen(evt); }; websocket.onclose = function(evt) { onClose(evt); }; websocket.onmessage = function(evt) { onMessage(evt); }; websocket.onerror = function(evt) { onError(evt); }; } function onOpen(evt) { writeToScreen("CONNECTED"); } function onClose(evt) { if (evt.code !== 1000) { // 正常关闭代码是1000 writeToScreen('<span style="color: red;">连接异常关闭: 代码=' + evt.code + ', 原因=' + (evt.reason || '未知') + '</span>'); } else { writeToScreen("DISCONNECTED"); } } function onMessage(evt) { writeToScreen('<span style="color: blue;">RESPONSE: '+ evt.data+'</span>'); } function onError(evt) { writeToScreen('<span style="color: red;">连接错误</span>'); } function doSend(message) { if (websocket.readyState === WebSocket.OPEN) { writeToScreen("SENT: " + message); websocket.send(message); } else { writeToScreen('<span style="color: orange;">消息发送失败: 连接未就绪</span>'); } } function writeToScreen(message) { var pre = document.createElement("p"); pre.style.wordWrap = "break-word"; pre.innerHTML = message; output.appendChild(pre); } window.addEventListener("load", init, false); function sendBtnClick(){ var msg = document.getElementById("input").value; if (msg.trim() !== '') { doSend(msg); document.getElementById("input").value = ''; } } function closeBtnClick(){ if (websocket) { websocket.close(1000, "用户主动关闭"); } } </script> <h2>WebSocket Test</h2> <input type="text" id="input" placeholder="输入消息..."></input> <button onclick="sendBtnClick()">发送</button> <button onclick="closeBtnClick()">关闭连接</button> <div id="output"></div> </body> </html>关键改进点
- 后端身份验证失败时:直接返回 HTTP 状态码,而不是尝试升级为 WebSocket
- 前端错误处理:在
onclose事件中检查关闭代码,判断是否为认证失败 - 连接状态检查:在发送消息前检查 WebSocket 连接状态
- 更详细的错误信息:提供更清晰的错误提示
这样修改后,当身份验证失败时,前端能够正确显示错误信息。
本回答被题主选为最佳回答 , 对您是否有帮助呢?解决 无用评论 打赏 举报