1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
|
package centrifuge
import (
"context"
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
"strings"
"testing"
"time"
"github.com/centrifugal/protocol"
"github.com/gorilla/websocket"
"github.com/stretchr/testify/require"
)
func sockjsData(data []byte) []byte {
quoted, _ := json.Marshal(string(data))
return []byte(fmt.Sprintf("[%s]", string(quoted)))
}
func TestSockjsHandler(t *testing.T) {
n, _ := New(Config{})
require.NoError(t, n.Run())
defer func() { _ = n.Shutdown(context.Background()) }()
mux := http.NewServeMux()
n.OnConnecting(func(ctx context.Context, event ConnectEvent) (ConnectReply, error) {
require.Equal(t, transportSockJS, event.Transport.Name())
require.Equal(t, ProtocolTypeJSON, event.Transport.Protocol())
require.Equal(t, EncodingTypeJSON, event.Transport.Encoding())
return ConnectReply{
Credentials: &Credentials{UserID: "user"},
Data: []byte(`{"SockJS connect response": 1}`),
}, nil
})
doneCh := make(chan struct{})
n.OnConnect(func(client *Client) {
err := client.Send([]byte(`{"SockJS write": 1}`))
require.NoError(t, err)
client.Disconnect(DisconnectForceReconnect)
})
mux.Handle("/connection/sockjs/", NewSockjsHandler(n, SockjsConfig{
HandlerPrefix: "/connection/sockjs",
}))
server := httptest.NewServer(mux)
defer server.Close()
url := "ws" + server.URL[4:]
conn, resp, err := websocket.DefaultDialer.Dial(url+"/connection/sockjs/220/fi0988475/websocket", nil)
require.NoError(t, err)
defer func() { _ = resp.Body.Close() }()
require.Equal(t, http.StatusSwitchingProtocols, resp.StatusCode)
require.NotNil(t, conn)
defer func() { _ = conn.Close() }()
_, p, err := conn.ReadMessage()
require.NoError(t, err)
require.Equal(t, "o", string(p)) // open frame of SockJS protocol.
connectRequest := &protocol.ConnectRequest{
Token: "boom",
}
params, _ := json.Marshal(connectRequest)
cmd := &protocol.Command{
ID: 1,
Method: protocol.MethodTypeConnect,
Params: params,
}
cmdBytes, _ := json.Marshal(cmd)
err = conn.WriteMessage(websocket.TextMessage, sockjsData(cmdBytes))
require.NoError(t, err)
go func() {
pos := 0
contentExpected := []string{
"SockJS connect response",
"SockJS write",
"force reconnect",
}
loop:
for {
_, p, err = conn.ReadMessage()
if err != nil {
break loop
}
for {
if strings.Contains(string(p), contentExpected[pos]) {
pos++
if pos >= len(contentExpected) {
close(doneCh)
break loop
}
} else {
break
}
}
}
}()
select {
case <-doneCh:
case <-time.After(5 * time.Second):
t.Fatal("timeout waiting for closing done channel")
}
}
|