Add gated fabric session websocket endpoint
This commit is contained in:
@@ -19,6 +19,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/example/remote-access-platform/agents/rap-node-agent/internal/authority"
|
||||
"github.com/example/remote-access-platform/agents/rap-node-agent/internal/fabricproto"
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
@@ -74,6 +75,80 @@ func TestMeshForwardingDisabled(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestFabricSessionWebSocketDisabledByDefault(t *testing.T) {
|
||||
server := httptest.NewServer(Server{Local: PeerIdentity{ClusterID: "cluster-1", NodeID: "node-a"}}.Handler())
|
||||
defer server.Close()
|
||||
|
||||
wsURL := "ws" + strings.TrimPrefix(server.URL, "http") + "/mesh/v1/fabric/session/ws"
|
||||
_, resp, err := websocket.DefaultDialer.Dial(wsURL, nil)
|
||||
if err == nil {
|
||||
t.Fatal("dial fabric session unexpectedly succeeded")
|
||||
}
|
||||
if resp == nil || resp.StatusCode != http.StatusNotFound {
|
||||
t.Fatalf("status = %v err=%v, want 404", resp, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFabricSessionWebSocketPingPongAndEvents(t *testing.T) {
|
||||
var events []FabricSessionEventLogEntry
|
||||
server := httptest.NewServer(Server{
|
||||
Local: PeerIdentity{ClusterID: "cluster-1", NodeID: "node-a"},
|
||||
FabricSessionEnabled: true,
|
||||
FabricSessionLogger: func(entry FabricSessionEventLogEntry) {
|
||||
events = append(events, entry)
|
||||
},
|
||||
}.Handler())
|
||||
defer server.Close()
|
||||
|
||||
wsURL := "ws" + strings.TrimPrefix(server.URL, "http") + "/mesh/v1/fabric/session/ws"
|
||||
conn, _, err := websocket.DefaultDialer.Dial(wsURL, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("dial fabric session websocket: %v", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
writeMeshFabricFrame(t, conn, fabricproto.Frame{Type: fabricproto.FramePing, Sequence: 17, Payload: []byte("probe")})
|
||||
pong := readMeshFabricFrame(t, conn)
|
||||
if pong.Type != fabricproto.FramePong || pong.Sequence != 17 || string(pong.Payload) != "probe" {
|
||||
t.Fatalf("pong = %+v", pong)
|
||||
}
|
||||
if len(events) < 2 || events[0].Event != "fabric_session_websocket_opened" || events[1].SessionEvent != fabricproto.SessionEventPing {
|
||||
t.Fatalf("events = %+v", events)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFabricSessionWebSocketOpenStreamDataAck(t *testing.T) {
|
||||
server := httptest.NewServer(Server{
|
||||
Local: PeerIdentity{ClusterID: "cluster-1", NodeID: "node-a"},
|
||||
FabricSessionEnabled: true,
|
||||
}.Handler())
|
||||
defer server.Close()
|
||||
|
||||
wsURL := "ws" + strings.TrimPrefix(server.URL, "http") + "/mesh/v1/fabric/session/ws"
|
||||
conn, _, err := websocket.DefaultDialer.Dial(wsURL, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("dial fabric session websocket: %v", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
writeMeshFabricFrame(t, conn, fabricproto.Frame{
|
||||
Type: fabricproto.FrameOpenStream,
|
||||
TrafficClass: fabricproto.TrafficClassInteractive,
|
||||
StreamID: 9,
|
||||
})
|
||||
writeMeshFabricFrame(t, conn, fabricproto.Frame{
|
||||
Type: fabricproto.FrameData,
|
||||
TrafficClass: fabricproto.TrafficClassInteractive,
|
||||
StreamID: 9,
|
||||
Sequence: 3,
|
||||
Payload: []byte("input"),
|
||||
})
|
||||
ack := readMeshFabricFrame(t, conn)
|
||||
if ack.Type != fabricproto.FrameAck || ack.StreamID != 9 || ack.Sequence != 3 {
|
||||
t.Fatalf("ack = %+v", ack)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMeshForwardingGateEnabledStillHasNoProductionRuntime(t *testing.T) {
|
||||
local := PeerIdentity{ClusterID: "cluster-1", NodeID: "node-b"}
|
||||
server := httptest.NewServer(Server{
|
||||
@@ -96,6 +171,36 @@ func TestMeshForwardingGateEnabledStillHasNoProductionRuntime(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func writeMeshFabricFrame(t *testing.T, conn *websocket.Conn, frame fabricproto.Frame) {
|
||||
t.Helper()
|
||||
encoded, err := fabricproto.MarshalFrame(frame)
|
||||
if err != nil {
|
||||
t.Fatalf("marshal fabric frame: %v", err)
|
||||
}
|
||||
if err := conn.WriteMessage(websocket.BinaryMessage, encoded); err != nil {
|
||||
t.Fatalf("write fabric websocket frame: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func readMeshFabricFrame(t *testing.T, conn *websocket.Conn) fabricproto.Frame {
|
||||
t.Helper()
|
||||
if err := conn.SetReadDeadline(time.Now().Add(2 * time.Second)); err != nil {
|
||||
t.Fatalf("set websocket read deadline: %v", err)
|
||||
}
|
||||
messageType, payload, err := conn.ReadMessage()
|
||||
if err != nil {
|
||||
t.Fatalf("read fabric websocket frame: %v", err)
|
||||
}
|
||||
if messageType != websocket.BinaryMessage {
|
||||
t.Fatalf("message type = %d, want binary", messageType)
|
||||
}
|
||||
frame, err := fabricproto.UnmarshalFrame(payload, fabricproto.DefaultMaxPayload)
|
||||
if err != nil {
|
||||
t.Fatalf("unmarshal fabric websocket frame: %v", err)
|
||||
}
|
||||
return frame
|
||||
}
|
||||
|
||||
func TestMeshForwardingGateDeliversFabricControlAtDestination(t *testing.T) {
|
||||
local := PeerIdentity{ClusterID: "cluster-1", NodeID: "node-c"}
|
||||
var events []ProductionForwardLogEntry
|
||||
|
||||
Reference in New Issue
Block a user