Skip to content

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

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?

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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