Przykład WebSocketu Fiber

Opierając się na komponencie WebSocket Fasthttp Fiber, używana jest metoda *fiber.Ctx, taka jak Locals, Params, Query i Cookies. Oto przykład użycia WebSocketu w Fiber.

Uwaga: Wymagana jest wersja Go 1.18 i wyższa.

Instalacja

go get -u github.com/gofiber/fiber/v2
go get -u github.com/gofiber/contrib/websocket

Sygnatura Funkcji

func New(handler func(*websocket.Conn), config ...websocket.Config) fiber.Handler {

Konfiguracja

Właściwość Typ Opis Wartość Domyślna
Filter func(*fiber.Ctx) bool Określa funkcję pomijania warstwy pośredniczącej. nil
HandshakeTimeout time.Duration HandshakeTimeout określa czas trwania negocjacji połączenia. 0 (brak limitu czasowego)
Subprotocols []string Subprotocols określa żądane przez klienta subprotokoły. nil
Origins []string Origins określa dozwolone źródła na podstawie nagłówka Origin. Jeśli jest puste, zezwala na dowolne źródła. nil
ReadBufferSize int ReadBufferSize określa rozmiar bufora wejścia/wyjścia dla odbieranych wiadomości (w bajtach). 0 (rozmiar domyślny)
WriteBufferSize int WriteBufferSize określa rozmiar bufora wejścia/wyjścia dla wysyłanych wiadomości (w bajtach). 0 (rozmiar domyślny)
WriteBufferPool websocket.BufferPool WriteBufferPool to pula buforów używana do operacji zapisu. nil
EnableCompression bool EnableCompression określa, czy klient powinien negocjować kompresję dla każdej wiadomości (RFC 7692). false
RecoverHandler func(*websocket.Conn) void RecoverHandler to funkcja obsługi do odzyskiwania z paniki. defaultRecover

Przykład

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 {
		// Zwraca true, jeśli klient żąda uaktualnienia do protokołu 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 jest dodane do *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"))
	// Dostęp do serwera WebSocket: ws://localhost:3000/ws/123?v=1.0
	// https://www.websocket.org/echo.html
}

Uwagi dotyczące Używania Warstwy Pośredniczącej Cache

Jeśli napotkasz błąd websocket: bad handshake podczas korzystania z warstwy pośredniczej pamięci podręcznej, użyj config.Next, aby pominąć ścieżkę 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) {}))

Rozważania dotyczące korzystania z oprogramowania pośredniczącego w odzyskiwaniu

Ze względów wewnętrznych oprogramowanie pośredniczące w odzyskiwaniu jest obecnie niekompatybilne z oprogramowaniem pośredniczącym w protokole WebSocket. Proszę użyć config.RecoverHandler, aby dodać obsługę odzyskiwania dla punktów końcowych protokołu WebSocket. Domyślnie konfiguracja RecoverHandler odzyskuje z panik, zapisuje ślad stosu do stderr i zwraca również odpowiedź zawierającą komunikat o panice w polu 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": "wystąpił błąd"})
        }
    },
}

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