WebSocket
基于 Fasthttp WebSocket 构建,适用于 Fiber,并可使用如 Locals, Params, Query 和 Cookies 等 *fiber.Ctx
方法。
注意: 需要 Go 1.18 及以上版本
安装
go get -u github.com/gofiber/fiber/v2
go get -u github.com/gofiber/contrib/websocket
签名
func New(handler func(*websocket.Conn), config ...websocket.Config) fiber.Handler {
配置
属性 | 类型 | 描述 | 默认值 |
---|---|---|---|
过滤器 | func(*fiber.Ctx) bool | 定义一个函数来跳过中间件。 | nil |
握手超时 | time.Duration | HandshakeTimeout 指定握手完成的持续时间。 | 0 (无超时) |
子协议 | []string | Subprotocols 指定客户端请求的子协议。 | nil |
源 | []string | 基于 Origin 头部的允许源。如果为空,则允许所有源。 | nil |
读取缓冲区大小 | int | ReadBufferSize 指定传入消息的 I/O 缓冲区大小(字节)。 | 0 (使用默认大小) |
写入缓冲区大小 | int | WriteBufferSize 指定传出消息的 I/O 缓冲区大小(字节)。 | 0 (使用默认大小) |
写入缓冲区池 | websocket.BufferPool | WriteBufferPool 是用于写入操作的缓冲区池。 | nil |
启用压缩 | bool | EnableCompression 指定客户端是否应尝试协商逐消息压缩(RFC 7692)。 | false |
恢复处理器 | func(*websocket.Conn) void | RecoverHandler 是一个 panic 处理函数,用于从 panic 中恢复。 | defaultRecover |
示例
package main
import (
"log"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/contrib/websocket"
)
func main() {
app := fiber.New()
app.Use("/ws", func(c *fiber.Ctx) error {
// IsWebSocketUpgrade returns true if the client
// requested upgrade to the WebSocket protocol.
if websocket.IsWebSocketUpgrade(c) {
c.Locals("allowed", true)
return c.Next()
}
return fiber.ErrUpgradeRequired
})
app.Get("/ws/:id", websocket.New(func(c *websocket.Conn) {
// c.Locals is added to the *websocket.Conn
log.Println(c.Locals("allowed")) // true
log.Println(c.Params("id")) // 123
log.Println(c.Query("v")) // 1.0
log.Println(c.Cookies("session")) // ""
// websocket.Conn bindings https://pkg.go.dev/github.com/fasthttp/websocket?tab=doc#pkg-index
var (
mt int
msg []byte
err error
)
for {
if mt, msg, err = c.ReadMessage(); err != nil {
log.Println("read:", err)
break
}
log.Printf("recv: %s", msg)
if err = c.WriteMessage(mt, msg); err != nil {
log.Println("write:", err)
break
}
}
}))
log.Fatal(app.Listen(":3000"))
// Access the websocket server: ws://localhost:3000/ws/123?v=1.0
// https://www.websocket.org/echo.html
}
关于缓存中间件的注意
如果你在使用 缓存中间件 时遇到错误 websocket: bad handshake
,请使用 config.Next
来跳过 websocket 路径。
app := fiber.New()
app.Use(cache.New(cache.Config{
Next: func(c *fiber.Ctx) bool {
return strings.Contains(c.Route().Path, "/ws")
},
}))
app.Get("/ws/:id", websocket.New(func(c *websocket.Conn) {}))
关于恢复中间件的注意
由于内部实现原因,目前恢复中间件不适用于 websocket 中间件,请使用 config.RecoverHandler
为 websocket 端点添加恢复处理器。默认情况下,config RecoverHandler
会从 panic 中恢复并将堆栈跟踪写入 stderr,同时返回一个包含 panic 消息的响应,该消息位于 error 字段中。
app := fiber.New()
app.Use(cache.New(cache.Config{
Next: func(c *fiber.Ctx) bool {
return strings.Contains(c.Route().Path, "/ws")
},
}))
cfg := Config{
RecoverHandler: func(conn *Conn) {
if err := recover(); err != nil {
conn.WriteJSON(fiber.Map{"customError": "error occurred"})
}
},
}
app.Get("/ws/:id", websocket.New(func(c *websocket.Conn) {}, cfg))
关于 WebSocket 子协议的注意
配置中的 Subprotocols
只帮助你协商子协议,并在找到合适的子协议时设置 Sec-Websocket-Protocol
头部。有关协商过程的更多信息,请查阅 fasthttp.Upgrader 中 Subprotocols
的注释。
所有连接都将发送到处理函数,无论子协议协商是否成功。你可以通过 conn.Subprotocol()
获取选定的子协议。
如果连接请求中包含 Sec-Websocket-Protocol
头部但协议协商失败,浏览器在收到升级响应后将立即断开连接。