Real-time chat with Websockets
Zak Burki
23-03-2017
Real Time Chat for Networking at Conferences. Join conference channels. View people. Then 1-to-1 chat to them.
http://near.pro
XMPP Bosh
Websockets
MQTT
CoAP
Protocols
sockets.io
sails.js (node.js framework)
nodejs-websocket
websocket
express-ws
ws
User
A
User
B
ChatRoom.
Conversation
ID
If User A sends a message in the chat room, and User B isn't connected - then send a Push notification instead.
Websocket Connection
Websocket Connection
Open a new websocket connection based on entry into conversation (chat-room) only.
ws endpoints instead of http
For example - ws://api.product.com/:conversationId?accessToken=MA_73XP87WG^oH[*bW12TpRXU;t$JD
var wsServer = require('./ws_routes/chat')(app,server,cookieParser,client);
config.ws + config.host + '/' + this.state.chatroomId + '?accessToken=' + this.state.token
RN Code:
Node Code:
Text
this.ws.onmessage = (e) => {
// a message was received
console.log('Received: ' + e.data);
if (e.data != 'ping') {
this.setState({
messages: this.state.messages.concat([JSON.parse(e.data)])
});
this.updateListChats();
}
};
updateListChats: function() {
...
// get current chatlist
var chatList = this.props.tabBar.mountedComponents["chats"].state.chats;
var found = false;
// map through the collections
chatList.map(function(conversation) {
// if the current iterated conversation is the one you're in, update its last message with the newly sent/received one
if (conversation._id === $this.state.chatroomId) {
found = true;
conversation.lastMessage = $this.state.messages[$this.state.messages.length - 1];
}
return conversation;
});
...
}
ws.on('message', function incoming(message) {
try {
var data = JSON.parse(message);
data['senderId'] = userData.userId;
console.log('Received Message: ', data); // JUST LOG THE MESSAGE ON THE SERVER
if (!data.senderId) {
console.log('Websocket Sending Error : no data.senderId');
return ws.send(JSON.stringify({
err: 'Sender is required'
}), function ack(wsError) {
if (wsError) console.log('Websocket Sending Error : no data.senderId', wsError);
});
}
var messageData = {
sender: data.senderId, // SHOULD BE FROM THE SESSION
message: data.message
} ...
if (!isOnChatroom) {
// PUSH NOTIF HERE ON RECEIVER ONLY
userModel.getDeviceToken(receiverId, function(err, res) {
if (err) console.log('Cannot Find User');
if (!res) console.log('Cannot Find User');
//console.log('Receiver Token: ', results);
if (res.token) {
apnService.pushMessage(res.token, userData.name,
chatroomId, results, userData, function() {
console.log('Notification Sent');
});
}
});
}
Check to see if other person (recipient of broadcast) is in the room and has a ws connection...if not..send them a push notification.
Websocket Protocol is not as mature as HTTP and the security measures are not as robust.
Check out Heroku's Websocket Security Blog for the implementation details.
Extending it for Group Chat.
exports.leaveGroup = function(req,res,next){
var userId = JSON.parse(req.session.userSession).userId;
var input = req.body;
if(!input.groupId){
return res.status(400).send('Group id is required');
}
Group.update({_id:input.groupId},{$pull:{"members" : {"id": userId}}},function(err,g){
if(err) return res.status(400).send(err);
res.sendStatus(200);
});
}
More work required on the chat broadcasting logic within a group, but keep simple!
Twitter: @zakburki