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 오류가 발생하는 경우 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": "error occurred"})
        }
    },
}

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