Skip to content

Unable to initialize a websocket ping-ponger before the first .Send() #3729

Open
@LandonTClipp

Description

@LandonTClipp

I asked this question in the examples repo but thought I would restate it here for visibility.

I have a websocket endpoint that streams server-side messages. The client will send nothing beyond pong messages. I am running into an issue where if the server has no messages to send when the websocket connection is first established, I cannot initialize the pingPonger goroutines because of how the generated code works. Here is our generated code:

// Send streams instances of "console.SubscribeResult" to the "subscribe"
// endpoint websocket connection.
func (s *SubscribeServerStream) Send(v *console.SubscribeResult) error {
	var err error
	// Upgrade the HTTP connection to a websocket connection only once. Connection
	// upgrade is done here so that authorization logic in the endpoint is executed
	// before calling the actual service method which may call Send().
	s.once.Do(func() {
		var conn *websocket.Conn
		conn, err = s.upgrader.Upgrade(s.w, s.r, nil)
		if err != nil {
			return
		}
		if s.configurer != nil {
			conn = s.configurer(conn, s.cancel)
		}
		s.conn = conn
	})
	if err != nil {
		return err
	}
	res := v
	body := NewSubscribeResponseBody(res)
	return s.conn.WriteJSON(body)
}

You can see that both the connection upgrader and the configurer are only run during the first .Send(). The obvious issue with this is that the lack of ping-pong messages causes the connection to go stale. More specifically, we use Cloudflare as an intermediary and it will eventually fail the connection with a gateway timeout error because of the lack of activity on the TCP connection.

Our only solution we've been able to find is to send an empty message through the connection in order to trigger the upgrader and configurer. This is non-ideal because it means the client receives an irrelevant message purely to workaround this "bug". Are there any other solutions to this that I am missing?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions