Fiber WebSocket の例

FiberのFasthttp WebSocketコンポーネントを使用して、*fiber.CtxメソッドがLocals、Params、Query、Cookiesなどを使用します。以下は、FiberでWebSocketを使用する例です。

注意: 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はメッセージの受信のためのI/Oバッファサイズを指定します(バイト単位)。 0 (デフォルトサイズ)
WriteBufferSize int WriteBufferSizeはメッセージの送信のためのI/Oバッファサイズを指定します(バイト単位)。 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 {
		// クライアントがWebSocketプロトコルへのアップグレードをリクエストする場合はtrueを返します
		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エラーが発生した場合は、WebSocketパスをスキップするためにconfig.Nextを使用してください。

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 ミドルウェアと互換性がありません。WebSocket エンドポイントのリカバリーハンドラを追加するには、 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))