iris v12 内置 websocket 不兼容标准协议,前端 new websocket() 会失败;必须用 gorilla/websocket(直连原生 api)或 go-socket.io(需配套客户端),且需正确配置路由、升级逻辑、nginx 及 tls。

iris/v12 自带的 websocket 包不支持标准 WebSocket 协议
直接调用 app.Get("/ws", websocket.Handler(...)) 会失败,因为 Iris v12 内置的 websocket 模块只是个轻量级连接管理器,底层没走 RFC 6455,也不兼容浏览器原生 WebSocket 构造函数。你用 new WebSocket("ws://...") 连上去,大概率触发 WebSocket connection to 'ws://...' failed。
这不是配置问题,是设计定位不同:Iris 的 websocket 专为内部长连接推送(如服务监控指标推送)设计,不面向跨域、多端、标准协议场景。
必须用 go-socket.io 或原生 gorilla/websocket
要让前端能用标准 WebSocket API 连接,两个主流选择:
-
go-socket.io:适合需要房间、命名空间、自动降级(轮询)、广播语义的业务,比如聊天室、协作白板。它模拟了 Node.js Socket.IO 的行为,但注意——客户端必须用socket.io-client,不能用原生WebSocket。 -
gorilla/websocket:零抽象,完全遵循 RFC 6455,浏览器new WebSocket()直连,适合自定义协议、低延迟要求高、或已有前端 WebSocket SDK 的项目(比如对接小程序、uni-app 的uni.connectSocket)。
两者不能混用。选错会导致握手失败、400 Bad Request 或连接后立即断开。
用 gorilla/websocket 接入 Iris 的正确姿势
Iris 是 HTTP 路由框架,WebSocket 升级需手动接管 http.ResponseWriter 和 http.Request。关键点:
- 路由必须注册为
app.Any("/ws", wsHandler)(不是Get),因为 WebSocket 握手是GET,但升级后复用同一连接,后续帧不是 HTTP 方法。 - 在 handler 中用
upgrader.Upgrade(w, r, nil),别漏掉nil第三个参数(header),否则某些代理(如 Nginx)会拦截升级请求。 - 升级成功后,
*websocket.Conn不属于 Iris 的Context生命周期,需自行管理读写并发(比如用conn.SetReadDeadline防僵死,用conn.WriteMessage而非fmt.Fprint)。
示例片段:
func wsHandler(ctx iris.Context) {
upgrader := websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool { return true }, // 生产需校验 origin
}
conn, err := upgrader.Upgrade(ctx.ResponseWriter(), ctx.Request(), nil)
if err != nil {
return
}
defer conn.Close()
for {
_, msg, err := conn.ReadMessage()
if err != nil {
break
}
if err := conn.WriteMessage(websocket.TextMessage, msg); err != nil {
break
}
}
}
生产环境必须处理的三个隐藏细节
本地跑通不等于线上可用:
- Nginx 配置要显式开启 WebSocket 支持:
proxy_http_version 1.1+proxy_set_header Upgrade $http_upgrade+proxy_set_header Connection "upgrade",缺一不可。 - 连接数暴涨时,
gorilla/websocket默认只允许 256 个并发读/写,需调conn.SetReadLimit()和conn.SetWriteDeadline(),并用sync.Pool复用[]byte缓冲区。 - Iris 的
app.Run()启动的是 HTTP 服务,无法监听wss://;启用 TLS 必须用app.Run(iris.TLS("cert.pem", "key.pem")),且证书需覆盖域名(不能用自签证书连小程序)。
这些点不提前验证,上线后会出现连接随机中断、iOS 小程序白屏、Chrome 控制台报 net::ERR_CONNECTION_CLOSED 等现象,排查起来非常耗时。











