gogo-fiber

For WebSockets client to Golang Fiber, how do you morph an HTTP client / connection into a WebSocket?


For background, see this recent stackoverflow article.

I am using Golang Fiber to set up a WebSockets service like this:

    app.Use("/ws", handler.UpgradeHandler)
    app.Get("/ws/:id", websocket.New(func(ws *websocket.Conn) {
        handler.MediaStreamHandler(ws)
    }))

with UpgradeHandler, the middleware, like so:

func UpgradeHandler(c *fiber.Ctx) error {
    // IsWebSocketUpgrade returns true if the client
    // requested upgrade to the WebSocket protocol.
    if websocket.IsWebSocketUpgrade(c) {
        log.Info("request to open WebSockets channel")
        return c.Next()
    }
    return fiber.ErrUpgradeRequired
}

The expectation is that an HTTP client to this service makes an HTTP GET request to something like http://chat.acme.ai:80/ws/123, and that coerces the Fiber server into opening up a WebSockets service. Eg:

func MediaStreamHandler(c *websocket.Conn) {
    ...
    for {
        if mt, buf, err = c.ReadMessage(); err != nil {
          ...
        }
        ...
    }

where we ingest streaming media until the WebSocket is closed.

QUESTION: if the client initiates an HTTP GET request to Fiber service to stand up the WebSockets service on Fiber's side, then how does the client-side logic morph its HTTP client into a WebSockets client?

Intuitively, we just have a socket somewhere, and upgrading an HTTP client to a WebSockets client is merely tacking on the right "glue" to the HTTP client. But from the perspective of using a canned solution like, say, Java WebSockets, it's not at all clear how you would morph the HTTP client into a WebSockets client.


Solution

  • Golang / Fiber are incidental here. By definition, the WebSockets protocol initiates an HTTP GET request to some service endpoint; during the handshake, the transport protocol is upgraded from HTTP to WebSockets. Part of that upgrade is that HTTP headers in both request and response are modified. See below for a chat-related example.

    Request headers, after upgrade:

    GET /chat HTTP/1.1
      Host: server.example.com
      Upgrade: websocket
      Connection: Upgrade
      Sec-WebSocket-Key: x3JJHmbDL1EzLkh9GBhXDw==
      Sec-WebSocket-Protocol: chat, superchat
      Sec-WebSocket-Version: 13
      Origin: http://example.com
    

    Server Response:

    HTTP/1.1 101 Switching Protocols
    Upgrade: websocket
    Connection: Upgrade
    Sec-WebSocket-Accept: HSmrc0sM1YUkAGmm50PpG2HaGWk=
    Sec-WebSocket-Protocol: chat
    

    These examples are from this article on WebSockets.