socket.io client doesn't set sid in requests - node.js

I'm trying to build a nodejs script to communicate with a socket.io server.
const io = require('socket.io-client');
const socket = io('http://192.168.144.249');
socket.on('connect', () => {
console.log('connected');
})
Using wireshark to follow traffic I can see the following:
So the browser sends me a sid, both in the response body and in the cookie.
Unfortunately, my following requests do not include this sid and I received a 400 Bad Request error:
When I try to build the same client from a browser windows I can see that this cookie is indeed set, both as cookie and as a query parameter:
I don't want to use a browser, I want to use a standalone node script. As far as I understood the parsing of the response and the inclusion of the session id should be done automatically by the socket.io-client. Am I wrong? If so, how can I intercept this event so that I can send the sid with following requests?
Am I supposed to first do a simple http request to the server, get the sid from there and then add it to the socket.io client when creating it using custom cookies or custom query parameters?
I can also see that the node standalone script is using engine.io version 4 (EIO=4 in the GET requests), while the browser is doing it with engine.io version 3, but the respose received seems to be exactly the same so I don't really think this is what is preventing my script from automatically completing the handshake with the server.

Well, I was wrong. It was indeed a protocol mismatch problem.
I was able to make my script working using socket.io-client#1.0.2. Install it with:
npm install socket.io-client#1.0.2

Related

gRPC response not getting sent to client inside setTimeout when running in renderer process in electron

I am using the #grpc/grpc-js module and I have setup a sample gRPC server:
When I run a gRPC server in electron, if I send a response after a "timeout", then the response is not going to the client at all. It's not closing the http2 stream properly. The same server works fine when run in node directly but giving this issue when run through electron.
The issue doesn't happen if I send the response directly outside the timeout function.
Sample Minimal Project which demonstrates the issue:
https://github.com/nateshmbhat/grpc-with-electron-sample-project
Expected Behavior
When the gRPC server sends the response with or without the timeout, the response should reach the client and the associated streams should close properly.
Actual Behavior
Though the server sends the response, the response is not reaching the client. So, the connection and stream don't close.
I have also filed issues for this here:
https://github.com/electron/electron/issues/26838
https://github.com/grpc/grpc-node/issues/1645

Can't set headers after they are sent error happens with socket.io

I am writing a very simple nodejs socket.io app. Somehow this returns "can't set headers after they are sent" error. but I can't see the point where the header is set again. I've only called server.listen once and I believe socket.listen works independently so it shouldn't conflict.
I am aware that can't set headers error had been posted a multiple times. I've read them briefly and I also understand how does response.writeHead works under normal circumstances(I've experimented with some node.js apps with response.writeHead, they worked fine most cases) it seems I am missing something from here. is it due to socket.io?
const fs = require("fs");
const server = require("http").createServer();
const io = require("socket.io").listen(server);
server.listen(52273,function(){
console.log("server up");
});
server.on("request",function(request,response){
fs.readFile("mainpage.html",function(error,data){
response.writeHead(200,{"Content-Type":"text/html"});
response.end(data);
});
});
io.sockets.on("connection",function(socket){
var roomName = null;
socket.on("join", function(data){
roomName = data;
socket.join(data);
console.log("client joined" + data);
});
socket.on("message",function(data){
io.sockets.in(roomName).emit("message","test");
});
});
It probably helps a bit here to understand a little bit about how socket.io works with your web server. socket.io uses the webSocket protocol as it's base protocol. A webSocket connection starts with an HTTP request that has special header set in it to indicate the start of a webSocket connection. A properly functioning web server will see this webSocket header and turn the request over to the webSocket handler to initiate the webSocket connection.
But, this handler you have:
server.on("request",function(request,response){
fs.readFile("mainpage.html",function(error,data){
response.writeHead(200,{"Content-Type":"text/html"});
response.end(data);
});
});
Looks like it is responding to every single request that arrives and sending a response, no matter what the request was. So, I can imagine that when the webSocket request comes in you're sending two responses, one from the webSocket server code and one from your request handler above.
Probably, you need to be able to only send your mainpage.html response for particular URLs that are not your webSocket request.
To see a little more about what's going in, insert a console.log() into here:
server.on("request",function(request,response){
console.log(request.url);
fs.readFile("mainpage.html",function(error,data){
response.writeHead(200,{"Content-Type":"text/html"});
response.end(data);
});
});
And, you will probably see you are sending your mainpage.html to a webSocket request which is not what you want to do. You will likely want to add some if logic so that your request handler is avoiding the webSocket requests.
What version of Node you using?
We had the same problem when we were using 0.9.x. I downgraded Node to 0.8.4 and the problem seems to have gone away.
My best guess is something in Node has changed that Socket.io doesnt agree with.
Thanks everyone. I've solved problem by installing express to my experiment app. I've read the manual again and discovered the socket.io v2 is now requiring express app as a dependency. It seems I have been using socket.io v2 but somehow sticked to socket.io v1 style app writing. It also worked when I downgraded it to socket.io v1.
TL;DR - socket.io v2 is not compatible with apps written for socket.io v1. When a socket.io app returns "can't set headers after they are sent" errors, try use proper version of the socket.io or install correct dependencies.

How can i get invalid request message from client in node js http module

As i asked,
I just want to know how to get invalid message from client in nodejs http server.
For example, normally client send "GET / HTTP/1.1\r\n\r\n" to server, But if i sent "VID / HTTP/1.1\r\n\r\n" like this, there is no react in server. I already checked that server computer gets "VID / HTTP/1.1\r\n\r\n" message using wire-shark.
Thank you for your help.
I looked the solution that using 404 response, But It not worked.
look at this server creation code
function server(Route,connect){
console.log("start server function");
function onRequest(req, response) { //req:clientrequest ,response : server response;
console.log("ans server");
Route(req,connect,response,hnd.Hnd);
}
http.createServer(onRequest).listen(port);
}
when I send message "GET /HTTP/1.1\r\n\r\n" from client, server console write "ans server". But not VID
VID is one kind of example that I assume protocol..
#slebetman : Thank you for your solution.
I've voted to close and link it to the appropriate question (see above). Unfortunately, you'll have to modify node in C and compile your own custom node.js. There have been requests for adding an API for this but so far it looks like it's not going anywhere: github.com/joyent/node/issues/3192 and github.com/joyent/http-parser/pull/158 – slebetman

Websocket server running fine but cannot connect from client (what url should I use?)

OK this is very simple to anyone who's used websocket and nodejs.
I have created a websocket server named ws_server.js and put it in C:\Program Files (x86)\nodejs where I have installed the nodejs framework. I started the server and it is running and it says it's listening on port 8080. So far so good, I have the server running.
Now I simply want to connect to it from client code so that I can do all that lovely stuff about capturing events using event listeners etc. The problem is, embarassingly, I cannot figure out what URL to use to connect to my websocket server.
function init() {
testWebSocket();
}
function testWebSocket() {
websocket = new WebSocket("ws://localhost:8080/"); // WHAT URL SHOULD BE USED HERE?
websocket.onopen = function(evt) { alert("OPEN") };
websocket.onclose = function(evt) { alert("CLOSE") };
websocket.onmessage = function(evt) { alert("MESSAGE") };
websocket.onerror = function(evt) { alert("ERROR") };
}
function doSend(message) {
// this would be called by user pressing a button somewhere
websocket.send(message);
alert("SENT");
}
window.addEventListener("load", init, false);
When I use ws://localhost:8080 the only events that trigger are CLOSE and ERROR. I cannot get the client to connect. I must be missing something very simple. Do I need to set up my nodejs folder in IIS for example and then use that as the URL?
Just to reiterate, the websocket server is running fine, I just don't know what URL to use to connect to it from the client.
EDIT: The websocket server reports the following error.
Specified protocol was not requested by the client.
I think I have got it working by doing the following.
var websocket = new WebSocket("ws://localhost:8080/","echo-protocol");
The problem being that I needed to specify a protocol. At least now I get the onopen event. ...if nothing much else
I was seeing the same error, the entire web server goes down. Adding the protocol fixes it but leaves me wondering why it was implemented this way. I mean, one bad request should not bring down your server.
You definitely have to encase it a try/catch, but the example code provided here https://www.npmjs.com/package/websocket (2019-08-07) does not. This issue can be easily avoided.
I just wanted to share a crazy issue that I had. I was able to connect to a websocket of an old version of a 3rd party app in one computer, but not to a newer version of the app in another.
Moreever, even in new computer with the new version of the app, The app was able to connect to the websocket, but no matter what I did, when I tried to connect with my own code, I kept getting the error message that the websocket connection failed
Long story short, They changed an apache configuration that allowed connecting to the websocket via a proxy.
In the old version, apache config was:
ProxyPass /socket/ ws://localhost:33015/ retry=10
ProxyPass /socket ws://localhost:33015/ retry=10
In the new version, apache config was changed to:
ProxyPass /socket/ ws://localhost:33015/ retry=10
By bad luck, I was trying to connect to ws://localhost/socket and not to ws://localhost/socket/. As a result, proxy was not found, and connection returned an error.
Moral of the story: Make sure that you are trying to connect to a websocket url that exists.
For me, the solution was to change the URL from ws:// to wss://. This is because the server I was connecting to had updated its security, and now only accepted wss.

Get a static request to push some data to clients using Node.js and Socket.io

I'm new to Node.js, and I've been playing with the "chat" example provided with the Socket.io install package. Is shows in a few lines of code how you can push some data to several clients (browsers) in a push-fashion (no pulling).
Here is the code on the server side : http://pastie.org/1537175
I get how you can send a message to a client with client.broadcast(msg), but I don't get how you can do it outside of the
io.on('connection', function(client){
... }
loop
I would like to invoke a client.broadcast(msg) when someone hits a particular url (like '/test.html'), see line #32. The device asking for the '/test.html' is not a typical "ajax-enabled" browser, but a mere text-based browser, so I cannot initialize an asynchronous request with the server. Any idea?
Thank you.
you can use .broadcast on your io object
case '/test.html':
io.broadcast('test'); // This is where I would like to invoke a client.broadcast(msg);
break;

Resources