From ad343a0f4ad175053f7d0da12a0587bcbb396d1c Mon Sep 17 00:00:00 2001 From: Joram Wilander Date: Tue, 12 Jul 2016 09:36:27 -0400 Subject: Added infrastructure for basic WebSocket API (#3432) --- model/websocket_client.go | 102 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 model/websocket_client.go (limited to 'model/websocket_client.go') diff --git a/model/websocket_client.go b/model/websocket_client.go new file mode 100644 index 000000000..7b9dc0b50 --- /dev/null +++ b/model/websocket_client.go @@ -0,0 +1,102 @@ +// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package model + +import ( + "encoding/json" + "github.com/gorilla/websocket" + "net/http" +) + +type WebSocketClient struct { + Url string // The location of the server like "ws://localhost:8065" + ApiUrl string // The api location of the server like "ws://localhost:8065/api/v3" + Conn *websocket.Conn // The WebSocket connection + AuthToken string // The token used to open the WebSocket + Sequence int64 // The ever-incrementing sequence attached to each WebSocket action + EventChannel chan *WebSocketEvent + ResponseChannel chan *WebSocketResponse +} + +// NewWebSocketClient constructs a new WebSocket client with convienence +// methods for talking to the server. +func NewWebSocketClient(url, authToken string) (*WebSocketClient, *AppError) { + header := http.Header{} + header.Set(HEADER_AUTH, "BEARER "+authToken) + conn, _, err := websocket.DefaultDialer.Dial(url+API_URL_SUFFIX+"/users/websocket", header) + if err != nil { + return nil, NewLocAppError("NewWebSocketClient", "model.websocket_client.connect_fail.app_error", nil, err.Error()) + } + + return &WebSocketClient{ + url, + url + API_URL_SUFFIX, + conn, + authToken, + 1, + make(chan *WebSocketEvent, 100), + make(chan *WebSocketResponse, 100), + }, nil +} + +func (wsc *WebSocketClient) Connect() *AppError { + header := http.Header{} + header.Set(HEADER_AUTH, "BEARER "+wsc.AuthToken) + + var err error + wsc.Conn, _, err = websocket.DefaultDialer.Dial(wsc.ApiUrl+"/users/websocket", header) + if err != nil { + return NewLocAppError("NewWebSocketClient", "model.websocket_client.connect_fail.app_error", nil, err.Error()) + } + + return nil +} + +func (wsc *WebSocketClient) Close() { + wsc.Conn.Close() +} + +func (wsc *WebSocketClient) Listen() { + go func() { + for { + var rawMsg json.RawMessage + var err error + if _, rawMsg, err = wsc.Conn.ReadMessage(); err != nil { + return + } + + var event WebSocketEvent + if err := json.Unmarshal(rawMsg, &event); err == nil && event.IsValid() { + wsc.EventChannel <- &event + continue + } + + var response WebSocketResponse + if err := json.Unmarshal(rawMsg, &response); err == nil && response.IsValid() { + wsc.ResponseChannel <- &response + continue + } + } + }() +} + +func (wsc *WebSocketClient) SendMessage(action string, data map[string]interface{}) { + req := &WebSocketRequest{} + req.Seq = wsc.Sequence + req.Action = action + req.Data = data + + wsc.Sequence++ + + wsc.Conn.WriteJSON(req) +} + +func (wsc *WebSocketClient) UserTyping(channelId, parentId string) { + data := map[string]interface{}{ + "channel_id": channelId, + "parent_id": parentId, + } + + wsc.SendMessage("user_typing", data) +} -- cgit v1.2.3-1-g7c22