1

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.

Kode Charlie
  • 1,297
  • 16
  • 32
  • Hm. [Here's an implementation in Go](https://github.com/gorilla/websocket/blob/main/client.go). It seems to create a raw connection, then use public components of the TLS, proxy, and HTTP libraries (e.g., [`req.Write`](https://pkg.go.dev/net/http#Request.Write)) to make the initial request asking for the upgrade from HTTP to WebSockets. – twotwotwo Aug 29 '23 at 22:57
  • So in this case, it's not that the websocket library has any special access to the internals of `net/http`, but that enough of the pieces of an HTTP client are separate public APIs that you can write code that uses a raw connection to send an HTTP(S) request, looks at the response, then switches to another protocol. For the general case, you probably want to look at the source code of the particular websocket library. – twotwotwo Aug 29 '23 at 23:02

1 Answers1

0

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.

Kode Charlie
  • 1,297
  • 16
  • 32