404 on websocket connection to Slack's RTM API - node.js

I am having the weirdest error when trying to connect to the RTM API from Slack.
I am implementing a simple bot in node, and I am using socket.io to handle the web socket connection. However, it always throws the error { [Error: xhr poll error] type: 'TransportError', description: 404 }
My code looks like this:
requester.GET({target: 'https://slack.com/api/rtm.start'}, [{key: 'token', value: config.token}], function(data) {
data = JSON.parse(data)
if (data.ok) {
let socket = require('socket.io-client')(data.url)
socket.on('connect', function(){})
socket.on('event', function(data){})
socket.on('disconnect', function(){})
socket.on('connect_error', function(err) {
console.log(err)
})
} else {
console.log(data)
}
})
requester is a file I wrote myself, handling simple HTTP calls, like GET here.
The thing is, I am using the URL returned by Slack the moment I get it, so why am I getting a code 404 ? What am I doing wrong ?

I don't think socket.io-client does what you want... I believe it's a client to talk to a server that's using socket.io (which Slack isn't). I believe socket.io-client is trying to make an HTTP request to the URL. You should be specifically using a WebSocket client. Maybe try the ws library?

Related

Strange numbers in SocketIo events data

I'm trying to learn SocketIo in NodeJS. I'm using .on and .emit functions with same event name but server dont see incoming event emitted by client but client recive some strange numbers as data to event.
I was trying to change .on to .addListener but this is still not working.
Server:
const io = require('socket.io');
const server = io.listen(8089);
server.on('connect', socket => {
console.log('New connection!') // this line is working fine!
socket.on('ping', incomingMessage => {
console.log('Incoming message!');
socket.emit('pong', incomingMessage);
});
});
Client code:
Im using cdn from: https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.2.0/socket.io.js
const server = io('http://127.0.0.1:8089');
server.on('connect', () => {
server.on('pong', message => {
console.log('Incoming message! ', message);
});
server.emit('ping', 'test message');
})
But i dont see 'Incoming message' in server side terminal. Client sucessfully connected to server socket and after ~ 5 seconds i recive strange messages like:
- Incoming message! 1
- Incoming message! 3
- Incoming message! 4
in webbrowser console (using Opera)
Ok so i fixed this issue :v the problem was ping-pong event names that already was used by socket.io if i changed event names everything is working fine.

Websockets using angular and Nodejs: How to send data to specific client

I am trying to use websocket.io with nodejs and angular. I am trying to build a one-to-one chat application. Here is snippets of my code:
server.js
app.io.on('connection', function(socket){
console.info(`Client connected [id=${socket.id}]`);
socket.on('disconnect', function(){
console.info(`Client gone [id=${socket.id}]`);
});
});
sendmessage.js
router.post("/auth/sendMessage", function(req, res) {
//rest api to handle send message
//mongodb insert
app.io.emit('new-message', { message: message});
}
Angular Client
this.socket.on("new-message", function(data) {
if (
data.message.conversationId === self.conversationId &&
data.message.sender === "customer"
) {
self.messages.push(data.message);
setTimeout(function() {
self.messagesDiv.nativeElement.scrollTop =
self.messagesDiv.nativeElement.scrollHeight;
}, 100);
}
});
Now, the problem that I am facing is new-message will send message to all the listeners. Although, I am handling the logic on the client side, to only show the message if it is sent by specific conversationId, this should be handled at the server end only due to security issues.
So, I want to be able to send to specific users only. I think this can somehow be done using socket.id which would be unique for each connection. But how can I pass this socket.id from client to server, so that server knows on which client it needs to send the data?
There are two things here, app.io and socket. In the first snippet, you use app.io.on('connection', function(socket){. This socket is the new connection. You can store this socket object somewhere in the database or in memory.
Now, app.io.emit will send the message to all the clients, while this socket that you stored somewhere will send the message to that particular client/user on socket.emit.
In short, you need to do
router.post("/auth/sendMessage", function(req, res) {
//rest api to handle send message
//mongodb insert
socket.emit('new-message', { message: message});
}
Here is a small tic-tac-toe game I made using sockets. It will give you more insight on how to use sockets. This is not perfect but you will still understand how to use sockets.
tl;dr save socket from app.io.on('connection'... and use socket.emit to send messages to that particular client.

Using Socket.IO in MeteorJS Server

i am trying top get socket.io working from the MeteorJS server. i am using the package from https://github.com/joncursi/socket-io-client, but i am unable to get it to work from the server and i cant figure out why.
i call the "connectToServer" method from the client, then this should contact the remote server and initialise the connection. when the code executes, i can see that the messages being logged, but nothing inside the "socket.on('connect',..." method. this suggests that it isn't making the connection. this is backed up by the fact that when i run code from the client side (using the the socket.io browser javascript code), i am able to connect without issues.
i have code on the server, whever there is an attempt to connect to the socket.io connection. this logged, with the client side code but not the server side code.
can anyone see what i may be doing wrong here?
Meteor.methods({
'connectToServer': function() {
socketioController();
}
});
function socketioController(){
var username = 'asd';
var password = 'asd';
console.log("trying to login with asd");
var socket = io('https://localhost:3001/');
console.log("socket variable set");
socket.on('connect', Meteor.bindEnvironment(function() {
console.log('Connected to the websocket!');
//Meteor.call('methodName1');
// on data event
socket.on('data-event', Meteor.bindEnvironment(function(data) {
console.log(data);
Meteor.call('methodName2');
}, function(e) {
throw e;
}));
// on disconnect
socket.on('disconnect', Meteor.bindEnvironment(function() {
console.log('Disconnected from the websocket!');
Meteor.call('methodName3');
}, function(e) {
throw e;
}));
}, function(e) {
throw e;
}));
}

How to emit server-side error and receive details about the error client-side, using Socket.IO?

Using socket.io, what is the prescribed method of emitting an error so that error information is sent to the client?
I have this:
socket.on('connection', function(socket) {
if (someError) {
emit('error', 'there is a error...');
}
};
I know that there is a way to do something like what I want by registering a middleware with socket.io, but I'm not sure what I would need to do from the middleware to transmit the error information back down to the client:
io.use(function(socket, next) {
next(new Error('An error has occurred.'));
});
Thanks in advance for any constructive guidance.
You appear to be emitting the error correctly on the server side, but you may also find the following syntax/example of interest:
socket.on('connection', function(socket) {
if (someError) {
this.emit('error', new Error('there is an error..'));
}
};
On the client-side you would need an error handler, here is an example of an 'error' handler:
socket.on('error', function (data) {
console.log(data || 'connect error - no data');
});
In this case, data should contain details about the error.
You do not need to register a middleware component for this behavior, this behavior exists out of the box.
References:
Client API Manager Documentation, describing events and parameters.
NodeWiz.biz article on Error Handling patterns in Node

Socket IO emitting multiple times (equal to number of clients connected) using sails js

I am trying to develop a simple socket io based chat app using sails MVC.
whenever a client connected socket emitting multiple times(equa to number of clients).
here is my code.
Server :
io=req.socket.manager;
var users=[];
io.sockets.on('connection', function(client) {
console.log("connected");
users.push(client.id);
client.on("chat", function(data) {
io.sockets.sockets[data.to].emit("chat", { from: client.id, to: data.to, msg: data.msg });
client.emit("chat", { from: client.id, to: data.to, msg: data.msg });
});
});
Client :
var socket=new io.connect('http://localhost:1337/');
socket.request('/Chat/index');
socket.emit('connection',function(data){
console.log(data);
});
socket.on('connect', function() {
console.log("Connected.");
//
});
socket.on('chat', function(data) {
console.log(data.msg );
});
please help me , is there any way to get actual socket object in sails?
I am using io=req.socket.manager; which is of req object.
the socket object should be accessible in sails.io on the server side
link
maybe you want to answer to a unique socket id? that can be achieved this way:
In the file sockets.js, at your config folder, find the onConnect property and add code like this:
onConnect: function(session, socket){
sails.io.sockets.socket(socket.id).send('YOUR_EVENT', {'message' : 'your message to a unique socket'});
}
It will send a unique message when a new connection is established. Just a couple of notes:
This can be considered a socket.io issue, not a sails issue, since the method .socket(socket.id) is part of socket.io
This was tested on sails v0.9.8, in other versions the file sockets.js might not be included in the default generated app with sails' new command
This is just an example to show how can it be done, you might need to adapt it to your needs.
Hope this helps.

Resources