Skip to content

Commit 6a03e6e

Browse files
committed
Add support for SDK-defined protocol format (JSON or Msgpack) via query parameter
1 parent a8f1c5c commit 6a03e6e

3 files changed

Lines changed: 22 additions & 20 deletions

File tree

protocol.go

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import (
66
"strconv"
77
"strings"
88

9-
"github.com/gorilla/websocket"
109
"github.com/vmihailenco/msgpack/v5"
1110
)
1211

@@ -99,16 +98,15 @@ type ErrorInfo struct {
9998
}
10099

101100
// ParseProtocolMessage decodes a WebSocket frame into a ProtocolMessage.
102-
// For text frames (JSON) and binary frames (msgpack).
101+
// The format is taken from the connection's "format" query parameter:
102+
// "msgpack" is decoded as msgpack, everything else (including "json" and an
103+
// absent value) is decoded as JSON.
103104
// Returns the parsed message. On failure, returns a message with Action=-1.
104-
func ParseProtocolMessage(data []byte, messageType int) ProtocolMessage {
105-
if messageType == websocket.TextMessage {
106-
return parseJSON(data)
107-
}
108-
if messageType == websocket.BinaryMessage {
105+
func ParseProtocolMessage(data []byte, format string) ProtocolMessage {
106+
if format == "msgpack" {
109107
return parseMsgpack(data)
110108
}
111-
return ProtocolMessage{Action: -1}
109+
return parseJSON(data)
112110
}
113111

114112
func parseJSON(data []byte) ProtocolMessage {

proxy_test.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@ func TestWsPassthrough(t *testing.T) {
315315
defer deleteSession(t, controlURL, session.SessionID)
316316

317317
// Connect through proxy
318-
conn := connectWs(t, fmt.Sprintf("localhost:%d", port), "key=test.key:secret")
318+
conn := connectWs(t, fmt.Sprintf("localhost:%d", port), "format=json", "key=test.key:secret")
319319
defer conn.Close()
320320

321321
// Should receive CONNECTED from mock upstream
@@ -467,7 +467,7 @@ func TestWsFrameSuppression(t *testing.T) {
467467
})
468468
defer deleteSession(t, controlURL, session.SessionID)
469469

470-
conn := connectWs(t, fmt.Sprintf("localhost:%d", port))
470+
conn := connectWs(t, fmt.Sprintf("localhost:%d", port), "format=json")
471471
defer conn.Close()
472472

473473
// Read CONNECTED
@@ -515,7 +515,7 @@ func TestWsInjectAndClose(t *testing.T) {
515515
})
516516
defer deleteSession(t, controlURL, session.SessionID)
517517

518-
conn := connectWs(t, fmt.Sprintf("localhost:%d", port))
518+
conn := connectWs(t, fmt.Sprintf("localhost:%d", port), "format=json")
519519
defer conn.Close()
520520

521521
// Should receive the injected DISCONNECTED message
@@ -672,7 +672,7 @@ func TestWsSuppressOnwards(t *testing.T) {
672672
})
673673
defer deleteSession(t, controlURL, session.SessionID)
674674

675-
conn := connectWs(t, fmt.Sprintf("localhost:%d", port))
675+
conn := connectWs(t, fmt.Sprintf("localhost:%d", port), "format=json")
676676
defer conn.Close()
677677

678678
// Read CONNECTED (arrives before suppress_onwards fires)
@@ -854,7 +854,7 @@ func TestRuleTimesLimit(t *testing.T) {
854854

855855
func TestProtocolParseJSON(t *testing.T) {
856856
msg := `{"action":10,"channel":"test-channel"}`
857-
pm := ParseProtocolMessage([]byte(msg), websocket.TextMessage)
857+
pm := ParseProtocolMessage([]byte(msg), "json")
858858
if pm.Action != ActionAttach {
859859
t.Fatalf("expected action %d, got %d", ActionAttach, pm.Action)
860860
}
@@ -865,7 +865,7 @@ func TestProtocolParseJSON(t *testing.T) {
865865

866866
func TestProtocolParseJSONWithError(t *testing.T) {
867867
msg := `{"action":9,"error":{"code":40142,"statusCode":401,"message":"Token expired"}}`
868-
pm := ParseProtocolMessage([]byte(msg), websocket.TextMessage)
868+
pm := ParseProtocolMessage([]byte(msg), "json")
869869
if pm.Action != ActionError {
870870
t.Fatalf("expected action %d, got %d", ActionError, pm.Action)
871871
}
@@ -885,7 +885,7 @@ func TestProtocolParseMsgpack(t *testing.T) {
885885
"channel": "test",
886886
}
887887
data := mustMarshalMsgpack(t, raw)
888-
pm := ParseProtocolMessage(data, websocket.BinaryMessage)
888+
pm := ParseProtocolMessage(data, "msgpack")
889889
if pm.Action != ActionAttach {
890890
t.Fatalf("expected action %d, got %d", ActionAttach, pm.Action)
891891
}

ws_proxy.go

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ func HandleWsProxy(session *Session, w http.ResponseWriter, r *http.Request) {
2828
}
2929
}
3030

31+
// Protocol format ("json" or "msgpack") is declared by the SDK via the
32+
// "format" query param and is fixed for the lifetime of the connection.
33+
format := queryParams["format"]
34+
3135
// Create WsConnection and register it
3236
wc := NewWsConnection(0)
3337
session.AddWsConn(wc)
@@ -142,13 +146,13 @@ func HandleWsProxy(session *Session, w http.ResponseWriter, r *http.Request) {
142146
// server → client relay
143147
go func() {
144148
defer wg.Done()
145-
relayFrames(session, wc, serverConn, clientConn, "server_to_client", "ws_frame_to_client")
149+
relayFrames(session, wc, serverConn, clientConn, "server_to_client", "ws_frame_to_client", format)
146150
}()
147151

148152
// client → server relay
149153
go func() {
150154
defer wg.Done()
151-
relayFrames(session, wc, clientConn, serverConn, "client_to_server", "ws_frame_to_server")
155+
relayFrames(session, wc, clientConn, serverConn, "client_to_server", "ws_frame_to_server", format)
152156
}()
153157

154158
wg.Wait()
@@ -163,7 +167,7 @@ func HandleWsProxy(session *Session, w http.ResponseWriter, r *http.Request) {
163167
}
164168

165169
// relayFrames reads frames from src and writes to dst, applying rules.
166-
func relayFrames(session *Session, wc *WsConnection, src, dst *websocket.Conn, direction, matchType string) {
170+
func relayFrames(session *Session, wc *WsConnection, src, dst *websocket.Conn, direction, matchType, format string) {
167171
for {
168172
if wc.IsClosed() {
169173
return
@@ -202,11 +206,11 @@ func relayFrames(session *Session, wc *WsConnection, src, dst *websocket.Conn, d
202206
}
203207

204208
// Parse protocol message for rule matching and logging
205-
pm := ParseProtocolMessage(data, msgType)
209+
pm := ParseProtocolMessage(data, format)
206210

207211
// Log the frame (as JSON for readability, even if binary)
208212
var logMsg json.RawMessage
209-
if msgType == websocket.TextMessage {
213+
if format != "msgpack" {
210214
logMsg = json.RawMessage(data)
211215
} else {
212216
// For binary frames, log the parsed summary

0 commit comments

Comments
 (0)