//我部署了一个gorilla的一个websocket
//路由:
func Router() (r []rest.Route) {
login_chk := services.NewLogin()
r = []rest.Route{
add_router(types.GET,"/ws/",WsChat), //
}
return r
}
type HandlerFunc func(w http.ResponseWriter, r *http.Request)
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,
}
}
type HandlerFunc func(w http.ResponseWriter, r *http.Request)
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,
}
}
//允许websocket
func WsChat(w http.ResponseWriter, r *http.Request) {
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
fmt.Printf("错误内容:%+v\n",err)
return
}
defer conn.Close()
// 设置关闭处理函数
conn.SetCloseHandler(func(code int, text string) error {
//处理下线逻辑
fmt.Printf("Connection closed [%s]\n", conn.RemoteAddr().String())
return nil
})
//fmt.Printf("Connection open [%s]:\n", conn.RemoteAddr().String())
for {
messageType, message, err := conn.ReadMessage()
if err != nil{
if websocket.IsCloseError(err, websocket.CloseNormalClosure, websocket.CloseGoingAway) {
fmt.Printf("连接关闭[%+v]\n", err)
}else{
fmt.Printf("连接异常关闭[%+v]\n", err)
}
break
}
if messageType == websocket.TextMessage {
//接收消息
fmt.Printf("Received [%s]:\nmessage:%s", conn.RemoteAddr().String(), message)
//发送消息
sendMsg := "服务器返回:" + string(message) + "[收到]"
err = conn.WriteMessage(messageType, []byte(sendMsg))
fmt.Printf("Send [%s]:\nmessage:%s", conn.RemoteAddr().String(), sendMsg)
if err != nil {
fmt.Println(err)
break
}
}
}
}
gorilla的源码中对请求的校验,server.go
136 if r.Method != http.MethodGet {
137 return u.returnError(w, r, http.StatusMethodNotAllowed, badHandshake+"request method is not GET")
138 }
也就是如果是post请求,将会报405,并返回包含request method is not GET的消息
但我用postman请求,返回的是404,并且没有错误消息


我怎样才能让gorilla抛出405,和request method is not GET
golang gorilla/websocket模拟post请求报错
- 写回答
- 好问题 0 提建议
- 关注问题
- 邀请回答
-
5条回答 默认 最新
檀越@新空间 2025-10-16 17:50关注下午好🌅🌅🌅
本答案参考通义千问根据你的描述,你正在使用 Gorilla WebSocket 来创建一个 WebSocket 服务,并且在尝试通过 POST 请求访问
/ws/路径时遇到了问题:返回 404 而不是预期的 405(Method Not Allowed),并且没有显示错误信息。这说明你的路由配置可能存在问题。
问题分析
-
WebSocket 路由只允许 GET 方法
Gorilla WebSocket 的Upgrade函数要求请求方法为GET,否则会返回405 Method Not Allowed错误,如你提到的源码部分所示。 -
你的路由配置中可能没有正确绑定
/ws/路由
从你提供的代码来看,Router()函数定义了/ws/路由,但你用的是types.Admin_Http_URL_Prefix + path,如果该前缀未正确设置或与实际路径不匹配,可能导致请求被错误地处理,从而返回 404。 -
POST 请求无法进入 WebSocket 处理逻辑
因为 WebSocket 升级只支持GET请求,所以如果你发送的是POST请求,Gorilla WebSocket 会在升级时抛出错误。但如果这个请求没有正确进入你的WsChat函数,可能是路由未被正确注册。
解决方案
1. 确保
/ws/路由正确注册检查
types.Admin_Http_URL_Prefix是否与你实际访问的 URL 匹配。例如:- 如果你访问的是
http://localhost:8080/ws/ - 那么
types.Admin_Http_URL_Prefix应该是"http://localhost:8080/"或者空字符串。 - 如果
types.Admin_Http_URL_Prefix是"api/",那么实际路径应为http://localhost:8080/api/ws/
重点:确保你的路由路径和实际访问路径完全一致
2. 检查是否将
/ws/路由绑定到正确的 HTTP 方法你目前的路由定义如下:
add_router(types.GET, "/ws/", WsChat)这意味着只有 GET 请求会被路由到
WsChat函数。而如果你用 POST 请求访问/ws/,它不会进入WsChat函数,而是可能被其他默认路由或错误处理逻辑捕获,导致返回 404。
3. 明确区分 WebSocket 和普通 HTTP 接口
WebSocket 的握手过程必须使用
GET请求,因此你不能用POST来测试 WebSocket 连接。POST 请求无法连接 WebSocket,这是协议层面的限制。重点:WebSocket 的握手只能使用 GET 方法,POST 请求无法建立 WebSocket 连接
4. 如何模拟 WebSocket 连接?
你可以使用以下方式测试 WebSocket:
✅ 使用 Postman 测试 WebSocket:
- 打开 Postman
- 设置请求类型为 WebSocket
- 输入地址:
ws://localhost:8080/ws/ - 发送消息,观察响应
✅ 使用命令行工具(如
wscat):npm install -g wscat wscat -c ws://localhost:8080/ws/
5. 如果你确实需要使用 POST 请求进行某些操作(非 WebSocket)
如果你希望使用 POST 请求来触发 WebSocket 消息或其他逻辑,可以考虑以下方式:
- 创建一个独立的 HTTP 接口(如
/send-message),接收 POST 请求 - 在该接口中,通过某种方式向 WebSocket 客户端发送消息(例如维护客户端列表)
- 示例代码如下:
func SendMessage(w http.ResponseWriter, r *http.Request) { if r.Method != "POST" { http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) return } // 读取 POST 数据 body, _ := io.ReadAll(r.Body) message := string(body) // 将消息广播给所有 WebSocket 客户端 for _, conn := range clients { err := conn.WriteMessage(websocket.TextMessage, []byte("Server received: "+message)) if err != nil { fmt.Println("Error sending message:", err) } } w.Write([]byte("Message sent")) }
6. 修改你的路由以包含 POST 接口(可选)
如果你希望同时支持 WebSocket 和 POST 接口,可以这样写:
r = []rest.Route{ add_router(types.GET, "/ws/", WsChat), add_router(types.POST, "/send-message", SendMessage), }
总结
| 步骤 | 内容 | |------|------| | 1 | 确保
/ws/路由路径正确,避免 404 | | 2 | WebSocket 握手只能使用 GET 方法,POST 无法建立连接 | | 3 | 使用 Postman 或 wscat 测试 WebSocket 连接 | | 4 | 若需 POST 接口,创建独立的 HTTP 接口并处理逻辑 |
最终建议
如果你的目标是 模拟 POST 请求,请不要尝试连接 WebSocket,而是使用标准的 HTTP POST 接口;
如果你的目标是 测试 WebSocket 连接,请使用 WebSocket 客户端工具(如 Postman、wscat)。如需进一步帮助,请提供完整的项目结构和启动代码,我可以帮你更详细地调试。
本回答被题主选为最佳回答 , 对您是否有帮助呢?解决 无用评论 打赏 举报-