Пример WebSocket Fiber

На основе компонента WebSocket Fasthttp в Fiber используется метод *fiber.Ctx, такой как Locals, Params, Query и Cookies. Вот пример использования WebSocket в Fiber.

Примечание: требуется версия 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 {

Конфигурация

Свойство Тип Описание Значение по умолчанию
Filter func(*fiber.Ctx) bool Определяет функцию для пропуска промежуточного уровня. nil
HandshakeTimeout time.Duration HandshakeTimeout указывает длительность для завершения рукопожатия. 0 (без тайм-аута)
Subprotocols []string Subprotocols указывают запрошенные клиентом подпротоколы. nil
Origins []string Допустимые источники на основе заголовка Origin. Если пусто, разрешает любые источники. nil
ReadBufferSize int ReadBufferSize указывает размер буфера ввода-вывода для получения сообщений (в байтах). 0 (стандартный размер)
WriteBufferSize int WriteBufferSize указывает размер буфера ввода-вывода для отправки сообщений (в байтах). 0 (стандартный размер)
WriteBufferPool websocket.BufferPool WriteBufferPool - это пул буферов, используемый для операций записи. nil
EnableCompression bool EnableCompression указывает, должен ли клиент переговоривать о сжатии для каждого сообщения (RFC 7692). false
RecoverHandler func(*websocket.Conn) void RecoverHandler - это функция обработки для восстановления после паники. 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 {
		// Возвращает true, если клиент запрашивает обновление до протокола WebSocket
		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 добавлен в *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")) // ""

		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"))
	// Доступ к серверу WebSocket: 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) {}))

Рекомендации по использованию промежуточного программного обеспечения для восстановления

Из-за внутренних причин реализации промежуточное программное обеспечение для восстановления в настоящее время несовместимо с промежуточным программным обеспечением для веб-сокетов. Пожалуйста, используйте config.RecoverHandler для добавления обработчика восстановления для конечных точек веб-сокетов. По умолчанию конфигурация RecoverHandler восстанавливает от паники, записывает след стека в stderr и также возвращает ответ, содержащий сообщение о панике в поле 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": "произошла ошибка"})
        }
    },
}

app.Get("/ws/:id", websocket.New(func(c *websocket.Conn) {}, cfg))