Sails and Socket publishUpdate Can't Send data - node.js

I try learn Socket With sails but I have a problem with publishUpdate can't send data.
Let me show my code
User Module server Side
'subscribe': function(req,res,next){
User.find(function(err,users){
if (err) return next(err);
User.watch(req.socket);
User.subscribe(req.socket, users);
console.log('now user is subscribe in ',req.socket.id);
res.send(200);
});
}
app.js Client Side
(function(io){
// Connect To Socket
var socket = io.sails.connect();
if(typeof console !== 'undefined'){
console.log('Connecting to Sails.js ...');
}
socket.on('connect', function(){
// is undefined
console.log("This is handshake: ",socket.handshake)
// is undefined
console.log("This is from the connect: ", socket.id);
//console.log(socket);
// listen for message
socket.on('message', function(message){
console.log('New Message is Coming', message);
});
// Subscribe to the user model classroom and instance room
io.socket.get('/user/subscribe',function(){
//console.log('user now is subscribe ');
});
// log
console.log(
'Socket is now connected and globally accessible as `socket`.\n' +
'e.g. to send a GET request to Sails, try \n' +
'`socket.get("/", function (response) ' +
'{ console.log(response); })`'
);
});
})(
// In case you're wrapping socket.io to prevent pollution of the global namespace,
// you can replace `window.io` with your own `io` here:
window.io
);
in Session module server Side
user.online = true;
user.save(function(err,user){
//req.isSocket
var io = sails.io;
// emit to all sockets (aka publish)
// including yourself
I try this and work great and I revived message
//io.sockets.emit('message', {thisIs: 'USer Log in Id is ' + user.id});
User.publishUpdate(user.id,{
loggedIn : true,
id : user.id
});
console.log('User is signin', user.id);
// User Redirect To His Profile
if (user.admin){
res.redirect('/user/');
return;
}
res.redirect('/user/show/'+ user.id);
});
Now I try reload the server and show me in chrome browser
This is handshake: undefined
app.js:14 This is from the connect: undefined
app.js:32 Socket is now connected and globally accessible as socket.
e.g. to send a GET request to Sails, try
socket.get("/", function (response) { console.log(response); })
I remove publishUpdate and try emit.
I try this and work great and I revived message.
//io.sockets.emit('message', {thisIs: 'USer Log in Id is ' + user.id});

Related

Angular 6 authentificate client after server restart socket.io socketio-jwt

Id like to auth eacht socket.io event on server side.
When i open angular page first, call method initSocket(login: Login), its ok.
Authentification successfull and i can send a message to server.
But if i restart server, angular reconnect to server by Htttp, but cant send a message by socketio.
In my server no messages in logs.
It seems that socketio-jwt block an clients message.
If i press F5 on client side its still ok again.
How to solve it without refreshing a page?
It seems taht i have to pass a token to each event on client side, after connection established to, but i dont know how to do it.
Angular 6:
public initSocket(login: Login): void {
this.socket = socketIo(SERVER_URL);
console.log('Socket init at' + SERVER_URL);
this.socket.emit('authenticate', { token: this.login.token });
this.socket.on('authenticated', function () {
console.log('socket is jwt authenticated');
});
this.socket.on('unauthorized', function (error, callback) {
if (error.data.type === 'UnauthorizedError' || error.data.code === 'invalid_token') {
// redirect user to login page perhaps or execute callback:
callback();
console.error('Users token has expired');
}
});
this.socket.on('disconnect', function (error) {
console.error('socket disconnect', error);
});
this.socket.on('connect_failed', function (error) {
console.error('socket connect_failed');
});
}
Server side:
io.sockets
.on('connection', socketioJwt.authorize({
secret: environment.secret,
timeout: 15000,
callback: false
})).on('authenticated', function (socket) {
clients[socket.decoded_token.id] = socket.decoded_token.login;
console.error('Connected: ', socket.decoded_token.login);
socket.on('message', async function (data) {
try {
// Проверка что пользователь пишите от себя
if (data.from === socket.decoded_token.id) {
data.totalCount = await db_helper.saveMessage(data);
if (clients[data.from] && clients[data.to]) {
io.sockets.connected[clients[data.to].socket].emit("message", data);
console.log("Sending from: " + clients[data.from].name + " to: " + clients[data.from].name + " '" + data.text + "'");
} else {
console.log('User does not exist: from=>', data.from, ':', clients[data.from], 'to=>', data.to, ':', clients[data.to]);
}
}
}
catch (error) {
console.error(error.message);
}
});
//Removing the socket on disconnect
socket.on('disconnect', function () {
});
});
This is because whenever your server/client goes offline, a new socket is created for re connection purpose and to establish a new connection i.e re connection, Server disconnects all it's previous connection from the same client, this process is asynchronous and thus is not visible to developers easily.
I would have also checked if my socket reconnection which is done is reconnected to the , by default socket reconnects to the port your client is connected to.
if that's the case then you need to reconnect with the help of io (socket manager)
There is also a possibility that your client re connection is set to false, you can check your socket properties by consoling it as follows:
this.socket.on('disconnect', function (error) {
console.log('disconnected', this)
//this sets whether the re connection is allowed or not
this.io._reconnection = true;
});
this.socket.on('reconnect', (error, callback) => {
console.log('reconnect succesfully', this);
//connect to the previously connected socket.
this.io.socket.reconnect()
});

Sails.js: stream socket and send to controller

I'm writing a REST API in Sails.js and alongside the regular HTTP routes, I need the application to listen for notifications on a socket from Salesforce.
I have a controller with some logic but I don't know how to get it to subscribe to the socket on startup, so right now nothing is reaching it.
Controller:
pushTopicHandler: function(req, res) {
if (!req.isSocket) {
return res.badRequest();
}
var nforce = require('nforce');
var org = nforce.createConnection({
clientId: sails.config.client_id,
clientSecret: sails.config.client_secret,
redirectUri: sails.config.callback_url + '/oauth/_callback',
mode: 'multi',
environment: 'sandbox'
});
org.authenticate({ username: sails.config.sfUsername, password: sails.config.sfPassword }, function(err, oauth) {
if(err) return res.serverError(err);
var str = org.stream({ topic: sails.config.push_topic, oauth: oauth });
str.on('connect', function(){
console.log('Connected to pushtopic: ' + sails.config.push_topic);
});
str.on('error', function(error) {
console.log('Error received from pushtopic: ' + error);
});
str.on('data', function(data) {
console.log('Received the following from pushtopic ---');
console.log(data);
});
});
}
Sails has a bootstrap.js file which lets you write anything you want to run before the server lifts.
I was able to subscribe to the push topic in a small function before the cb() in that file and it works, the server starts the REST API normally and it's still listening for events.

Client is trying to get data with Socket.io but doesn't seem to connect

I have set up sockets on my client and server, but I can't seem to get my data to come into my client. It seems they are connecting properly, I just can't get any data to come through. There are no error messages either.
Here is my server code:
io.on('connection', function (socket) {
console.log('a user connected');
socket.on('custom-message', function () {
console.log("Hitting messages socket");
Message.find(function(err, messages){
if(err){
socket.emit('custom-message', err)
} else {
socket.emit('custom-message', messages);
}
})
});
});
Here is the function in the client that connects to the socket:
loadMessagesFromServer: function(){
console.log("About to load messages")
socket.on('custom-message', function(msg){
console.log("connected in client", msg)
});
},
Like I said it is a pretty simple example, I just can't seem to get the data in loadMessagesFromServer .. And there are no erros, the only way I have been debugging is trying different things..
You are listening on the event messages. So you need to emit the same event not socket.emit('messages: err', err). Try with socket.emit("messages", error). Moreover, in your server-side code, you need first to receive a message event and only then your socket will emit the messages. Remove the socket.on(custom-messages). Why do you need it?
Server-side code
io.on('connection', function (socket) {
/* Here a client connection is established. The on("connection")
* event will be triggered as many times as`io.connect("the-uri")`
* is triggered (and succeeded) in the client`
*/
// Listening for the post event
socket.on("post", function(messages){
console.log("client posted data:", messages)
// Find messages and emit result
Message.find(function(err, messages){
if(err){
socket.emit('error', err)
} else {
socket.emit("message", messages);
}
});
});
});
Client-side code
registerOnMessageFromServerListener: function(){
socket.on("message", function(msg){
console.log("received message:", msg);
});
registerOnErrorFromServerListener: function(){
socket.on("error", function(error){
console.log("an error occured:", error);
});
registerOnMessageFromServerListener();
registerOnErrorFromServerListener();
socket.emit("post", "a-message");
Also make sure that you call the loadMessagesFromServer before you establish the socket connection

socket.io emit only to sender outside the socket.on('connect')

Is it possible to global emit only to sender but outside the socket.on('connect') event? I'm looking for something like socket.broadcast.to().emit() which I can use in app.post method, which is not in connect method, so I can't use just socket.emit
app.post('/room', function(req, res) {
io.sockets.emit('something');
});
'something' I want to emit only to SENDER
My code:
socket_id;
app.post('/room', function(req, res) {
if (req.body.user == ''){
io.sockets.socket(socket_id).emit('usernameError', 'Type your username');
}
else if (users[req.body.user] !== undefined ) {
io.sockets.socket(socket_id).emit('usernameError', 'Username exists.');
}
else{
users[req.body.user] = req.body.user;
user = req.body.user;
io.sockets.emit('newUser', user+' join to the room');
res.render('room');
}
});
io.sockets.on('connection', function(socket) {
socket.username = user;
socket.join('room1');
socket.id = socket_id;
});
As far as I understand you want to send "something" to the user that just came to /room page, right?
If so, you can't do it in app.post method because this code will execute before the client will receive the HTML code,
and thus handshake between client and server will not be established.
I think the best solution would be executing the following code on the client side on /room page only:
var socket = io.connect('/'); //your socket.io connection (may be different)
socket.on('something', function(data) {
console.log(data);
});
socket.emit('i_am_room_page'); //tell server we are on /room page
And on the server:
io.sockets.on('connection', function(socket) {
socket.on('i_am_room_page', function(data) {
socket.emit('something', {your: 'data'});
});
});
Hope this helps
If somehow you can store the socektID of the sender in a variable, then you can emit to that particular client in app.post method. Do something like this:
var id;
io.sockets.on('connection', function(socket){
socket.on('some event'){
id = socket.id;
}
});
and do this in app.post method:
app.post('/room', function(req, res) {
io.sockets.socket(socketid).emit('event name', {data: yourData});
});
Though I've proposed this solution but your approach doesn't seem too convincing.

need to send error to unauthorized user in socket.io

as the title is obvoius i need to send back some error message for unauthorized user and i need to know how to achive this for example i need to send this message to user
you dont have any username to begin chat
and print it in users browser how should i do that? the client side code is something like this
//this is the client side code
var socket = io.connect('http://localhost', { resource: '/chat/app.js' });
// on connection to server, ask for user's name with an anonymous callback
socket.on('connect', function(){
// call the server-side function 'adduser' and send one parameter (value of prompt)
socket.emit('adduser')
});
socket.socket.on('error', function (reason){
console.log('Unable to connect Socket.IO', reason);
});
but the reason which i get in console is
Unable to connect Socket.IO handshake error
how should i print the message which is the cause of user is nothing get authorized?
this is the server side code
var io = require('socket.io').listen(80);
io.configure(function (){
io.set('authorization', function (handshakeData, callback) {
// findDatabyip is an async example function
findDatabyIP(handshakeData.address.address, function (err, data) {
if (err) return callback(err);
if (data.authorized) {
handshakeData.foo = 'bar';
for(var prop in data) handshakeData[prop] = data[prop];
callback(null, true);
} else {
//THIS IS THE MESSAGE *********************************************
callback('you dont have any username to begin chat', false);
}
})
});
});
To send the error back to the user you must modify the error function on manager.js (socket.io\lib\manager.js; line 768 approx) from this
function error (err) {
writeErr(500, 'handshake error');
self.log.warn('handshake error ' + err);
};
to this
function error (err) {
writeErr(500, /*'handshake error'*/ err);
self.log.warn('handshake error ' + err);
};

Resources