Iris本身不内置WebSocket支持,因其仅为HTTP框架;需通过gorilla/websocket等第三方库手动桥接,将升级逻辑挂载为普通HTTP路由并禁用干扰中间件。

iris 本身不内置 WebSocket 支持,它是个 HTTP 框架,不是全栈实时通信框架。想在 Iris 上跑 WebSocket,得靠第三方库桥接,最常用的是 gorilla/websocket 或 go-socket.io ——但后者和 Iris 的集成需要手动适配,不能直接用 app.Get() 注册 WebSocket 路由。
为什么 iris.WebSocket() 不存在?
iris 的路由系统只处理 HTTP 请求生命周期(GET、POST 等),而 WebSocket 升级请求(Upgrade: websocket)需要底层接管连接,绕过标准 HTTP 中间件链。所以你不会在官方文档里找到 app.WebSocket() 或类似 API。
用 gorilla/websocket 在 Iris 里接 WebSocket 连接
这是目前最轻量、最可控的方式。关键点是:把 WebSocket 升级逻辑写成一个普通 HTTP handler,再挂到 app.Get() 或 app.Any() 上,然后手动调用 upgrader.Upgrade()。
常见错误现象:http: response.WriteHeader on hijacked connection 或浏览器报 Error during WebSocket handshake: Unexpected response code: 200 —— 基本都是因为没正确 hijack 连接,或者中间件(比如 iris.Compression)提前写了响应头。
- 禁用所有可能干扰响应头的中间件(尤其是压缩、CORS 预检拦截器)
- 确保 handler 函数里没有调用
ctx.WriteString()、ctx.JSON()等任何写响应体的操作 - 升级后立即 return,别让 Iris 继续执行后续 middleware 或自动写 status
示例片段:
var upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool { return true }, // 生产环境需严格校验
}
<p>func wsHandler(ctx iris.Context) {
conn, err := upgrader.Upgrade(ctx.ResponseWriter(), ctx.Request(), nil)
if err != nil {
return // 不要 panic,也不要 ctx.StatusCode(500)
}
defer conn.Close()</p><pre class="brush:php;toolbar:false;">for {
_, msg, err := conn.ReadMessage()
if err != nil {
break
}
if err := conn.WriteMessage(websocket.TextMessage, append([]byte("echo: "), msg...)); err != nil {
break
}
}}
注册方式:
app.Get("/ws", wsHandler)
go-socket.io 和 Iris 共存要注意什么?
go-socket.io 是独立 HTTP server,它监听自己的端口(比如 :8081),和 Iris 的 :8080 是两套服务。强行塞进 Iris 的 http.ServeMux 会出问题,因为 go-socket.io 内部依赖自己的 http.Server 和路由树。
实际部署时常见坑:
- 前端连
ws://localhost:8080/socket.io/却收不到404或连接被重置 —— 因为 Iris 没转发,也没暴露 socket.io 的静态资源路径 - 用了
iris.Compression后,socket.io 的长轮询(polling)降级失败 ——go-socket.io对压缩头敏感,必须关掉 - session 共享困难:Iris 的
ctx.SessionID()和go-socket.io的conn.Context()完全隔离,没法直接复用
如果硬要共用端口,只能用反向代理(比如 Nginx)把 /socket.io/ 路径转发到 go-socket.io 实例;或改用 net/http 原生 Server + go-socket.io,把 Iris 的路由挂到同一个 http.ServeMux 下(但会失去 Iris 中间件能力)。
客户端连不上?先检查这三件事
无论用哪种后端方案,前端连不上基本逃不开:
- 浏览器控制台是否报
WebSocket connection to 'ws://...' failed?看具体错误码:ERR_CONNECTION_REFUSED是服务没起来,ERR_CONNECTION_CLOSED是握手后立刻断开(大概率后端 handler panic 或没 hold 住连接) - 确认服务端监听的是
ws://(开发用)还是wss://(生产必须 TLS),且端口没被防火墙或公司代理屏蔽 - Iris 启动时用了
iris.WithoutVersionHeader或其他非标准选项?某些 WebSocket 客户端库对响应头敏感,建议启动时显式加iris.WithoutServerError避免干扰
真正容易被忽略的点:Iris 默认启用 iris.WithOptimizations,它会自动压缩响应体 —— 但 WebSocket 升级响应绝对不能被压缩,否则协议握手失败。务必在注册 WebSocket handler 前,确保该路由路径已排除所有中间件影响。











