goadesign / goadesign/goa

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

Open
#3,729 7 comments 0 reactions 0 assignees View on GitHub
Dominant language
Go
Stars
6.1k
Forks
583
Avg merge
2d 10h
Merged PRs (30d)
15

Description

I asked this question in the [examples repo](https://github.com/goadesign/examples/issues/165) 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:

```go
// 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?

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.