Description
I am trying to find a way to stream arbitrary binary data over websockets. This server is intended to be a lean IoT data ingestion server and the payload needs to be as small as possible to minimize data usage. I'm using goa since it is part of a monorepo that already uses goa for other services and wanted to keep things consistent. As there weren't any examples for this, I tried the following design:
package design
import (
. "goa.design/goa/v3/dsl"
_ "goa.design/plugins/v3/zaplogger"
)
var _ = Service("data-ingestion", func() {
Error("Unauthorized")
Method("v1", func() {
StreamingPayload(String)
StreamingResult(String)
HTTP(func() {
GET("/di/v1")
})
})
Method("health-probe", func() {
Result(String)
HTTP(func() {
GET("/ping")
})
})
})
This generates the following Recv()
in gen/data_ingestion/server/websocket.go
:
// Recv reads instances of "string" from the "v1" endpoint websocket connection.
func (s *V1ServerStream) Recv() (string, error) {
var (
rv string
msg *string
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 Recv().
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 rv, err
}
if err = s.conn.ReadJSON(&msg); err != nil {
return rv, err
}
if msg == nil {
return rv, io.EOF
}
return *msg, nil
}
As you can see, this will fail for all messages due to the use of s.conn.ReadJSON
:
[KV8BQbVR] [KV8BQbVR] encoding: json: cannot unmarshal object into Go value of type string
Is this an invalid use of StreamingPayload? In which case, maybe there could be an error message during generate?
Other than that, is there currently any way to stream binary data over websockets?