socketio + sails: does not receive response in socket frame - node.js

I created a socket server with sails. I use socket.io.js and sails.io.js to test, but the results are not the same
I couldn't find the reason why.
I want to fix socket.io to work the same as sails.io, for clients not using the sails framework
In my sample,
I created ChatController in sails server
/**
* ChatController
*/
module.exports = {
subcriber: function (req, res) {
return res.send('done');
},
};
In client code, I try socket.io and sails.io in turn. Both were able to call the function (by see the log on the server), but the client using socket.io did not receive the response like sails.io
client use sails.io
io.socket.get('/chat/subcriber', function responseFromServer(body, response) {
console.log("The server responded with status " + response.statusCode + " and said: ", body);
});
and client use socket.io
<script src="/socket.io/socket.io.js"></script>
var socket = io('http://localhost:1337/', {
transports: ['websocket'],
query: SDK_INFO.versionString
});
socket.emit('get', { method: "get", headers: {}, data: {}, url: "/chat/subcriber" });
This is results
client use socket.io https://prnt.sc/n2ya3w
client use sails.io https://prnt.sc/n2y9yz
I would like for the client to use socket.io can also get a response like the client use sails.io
Can anyone give me experience on this issue?
Thanks

Related

Why does Socket.io server override node http middleware?

I have made a React application which relies fully on WebSockets after the initial HTTP Upgrade. For security reasons i use a cookie AND a JWT token in my WebSockets connection.
It all works fine, but when opening a new tab, socket.io cookies get reissued and I want users to stay logged in over multiple tabs. So i want to set a cookie if the client doesn't already have one. If it already has one, then use that cookie.
So I want to handle the first HTTP polling requests and created middleware for that in Node's http server:
// HTTP SERVER
const server = require('http').createServer(function (request, response) {
console.log('test');
console.log(request);
if(!request.headers.cookie) { // cookie pseudo-logic
response.writeHead(200, {
'Set-Cookie': 'mycookie=test',
'Content-Type': 'text/plain'
});
}
// Socket.IO server instance
const io = require('socket.io')(server, {
origins: config.allowedOrigins,
cookie: false, // disable default io cookie
});
server.listen(port, () => console.log(`Listening on port ${port}`));
I use Socket.io as WebSockets framework. The problem however is that this middleware get's ignored, when registering the Socket.io server. When i comment out the Socket.io server, the middleware is active and the request get's logged.
It looks like Socket.io's server is overriding the handler for node http's server. In the Socket.io docs however they provide this example:
var app = require('http').createServer(handler)
var io = require('socket.io')(app);
var fs = require('fs');
app.listen(80);
function handler (req, res) {
fs.readFile(__dirname + '/index.html',
function (err, data) {
if (err) {
res.writeHead(500);
return res.end('Error loading index.html');
}
res.writeHead(200);
res.end(data);
});
}
io.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});
Thus indicating that it should be possible to handle thw first http polling requests and also the socket requests. I managed to get it work with Express, but I don't understand why node's http server can't.
Anybody who knows what's happening?
Thanks in advance,
Mike
Because normal usage of socket.io does not want regular http middleware to see socket.io connection requests (they would normally trigger 404 responses), socket.io places its own request handler first in line before any others, even ones that existed before it was installed.
You can see how it does that here: https://github.com/socketio/engine.io/blob/master/lib/server.js#L437 in the engine.io source.
I can think of the following ways for you to pre-process a request before socket.io sees it:
Use a proxy and do your cookie stuff in a proxy before socket.io even sees the request.
Patch socket.io/engine.io code to add a callback hook for what you want to do.
Copy the technique used by socket.io/engine.io to put your own request handler first in line after socket.io is configured.
Find a way to override the socket.io server object's handleRequest() method which is what gets called when there's an incoming connection request. You can see its code here.

node.js - issue with faye-websocket-node as client and sockjs-node as server

I'm trying to use faye-websocket-node ^0.11.0 as client, sockjs-node 0.3.18 as server, please refer to below client/server code
Issue:
if client and server prefix matchs, like below code prefix = /hello, client will throw Error during WebSocket handshake: Unexpected response code: 200
I tried using prefix = / on the server, this time there won't be any error message, but there's no connection open, no message printed from either client or server on open or on connection code
Question:
How to use faye-websocket-node as client, sockjs-node as server, and have them communicate via websock using node.js?
Thanks!
client code:
var WebSocket = require('faye-websocket'),
ws = new WebSocket.Client('ws://127.0.0.1:8888/hello');
ws.on('open', function(event) {
console.log('open');
ws.send('Hello, world!');
});
ws.on('message', function(event) {
console.log('message', event.data);
});
ws.on('close', function(event) {
console.log('close', event.code, event.reason);
ws = null;
});
ws.on('error', function(event){
console.log('error', event.message);
});
server code:
var sockjs = require('sockjs');
var http = require('http');
var sockjsServer = sockjs.createServer({
sockjs_url: '//d1fxtkz8shb9d2.cloudfront.net/sockjs-0.3.min.js'
});
sockjsServer.on('connection', function(conn) {
console.log('on connection');
conn.on('data', function(msg) {
console.log('\nRECV:'+msg);
});
});
var server = http.createServer();
sockjsServer.installHandlers(server, {prefix:'/hello'});
server.listen(8888, '0.0.0.0');
I raised ticket#229, answer from sockjs-node:
You cannot use faye-websocket directly as SockJS utilizes additional framing. You can do one of two things:
1. Use the "raw" endpoint as documented in the README: https://github.com/sockjs/sockjs-node#connecting-to-sockjs-node-without-the-client
2. Use sockjs-client from Node.js! Client versions >= 1.0 support usage directly from Node.

Failed to load resource: the server responded with a status of 426 (Upgrade Required)

I tried to go with the tutorial of this link http://web-engineering.info/node/57
But when I execute node server.js and open the browser http://localhost:3434 it says upgrade required. The server.js file is:
var WebSocketServer = require('ws').Server,
wss = new WebSocketServer({port: 3434});
wss.broadcast = function (data) {
var i = 0, n = this.clients ? this.clients.length : 0, client = null;
for (; i < n; i++) {
client = this.clients[i];
if (client.readyState === client.OPEN) {
client.send(data);
}
else console.error('Error: the client state is ' + client.readyState);
}
};
wss.on('connection', function (ws) {
ws.on('message', function (message) {
wss.broadcast(message);
});
});
you have to open your index.html in browser not http://127.0.0.1:3434
its a websocket server. You are trying to make a http connection to a websocket server.
Most probably your server socket at localhost:3434 don't have support for websocket, so the connection is terminated by the client browser.
This error indicates that on localhost:3434 you are running a HTTP server which is incapable to "upgrade" to websocket.
(Since both simple http and websocket begins with a simple http request. In that http request the client ask the server to switch to websocket protocol.)
Should you add this ?
var ws = require('websocket.io')
, server = new ws.Server()
// … somewhere in your http server code
server.on('upgrade', function (req, socket, head) {
server.handleUpgrade(req, socket, head);
});
ref https://www.npmjs.com/package/websocket.io#passing-in-requests
Check this SO too What is an http upgrade?
I tried intercepting the http request
var ws = require('websocket.io')
, http = require('http').createServer().listen(3000)
, server = ws.attach(http)
server.on('connection', function (socket) {
socket.on('message', function () { });
socket.on('close', function () { });
});
https://www.npmjs.com/package/websocket.io#passing-in-requests
For me using the npmjs documentation, I went copy-paste rogue.
Then, debugging my client-side request I noted that the URL parameter I was using was not a string as expected.
But it was shark_s's answer that helped remind me to go look at the console and interpret the error again- so thanks.

how to flush the buffer in TCP connection

Hi I am facing issue with a server client message passing from web client to TCP server . Every time I reconnect to the web page my first 6 messages passes with out delay and the seventh message takes lots of time and the first message repeats again. I think there should be some handler for buffer but I have no idea of how to start it. Help me to solve this. My server and client both are in node socket ( using var net = require('net') ).
my client has to send a response for the ajax call which i made from web page:
$.ajax({
type: 'POST',
url: 'http://localhost:3000/client',
dataType: "json",
contentType: "application/json; charset=UTF-8",
data: JSON.stringify({name:data+'\r'}),// this is the data i get from web page
done : function(data){
console.log('on success', data);
},
fail : function(error){
console.log('on error', error)
}
})
and my node client
var net = require('net');
var _ = require('lodash');
router.post('/client', function(req, res) {
var inputJSON = req.body;
var HOST = '127.0.0.1';
var PORT = 5000;
var client = new net.Socket();
client.connect(PORT, HOST, function() {
console.log('CONNECTED TO: ' + HOST + ':' + PORT);
// Write a message to the socket as soon as the client is connected, the server will receive it as message from the client
_.forEach(inputJSON, function(value,key){
client.write(value);
// console.log(value);
})
});
//This is the line i missed in my earlier program the client should respond
res.send('success')
});
I am learning node. so you can improvise my code with your comments so i can improve better thanks.

Using node.js to proxy http and websocket traffic

I'm expanding on a node.js reverse proxy I put together with mikeal's request module: https://github.com/mikeal/request . It is a connect app that uses a small piece of custom middleware to check if the the current request is for an API route and if so it proxies it to and from a different API server like this:
.use(function(req, res, next){
if( /^\/api\//.test(req.url) ){
req.pipe(request(apiUrl + req.url))
.on('error', function(err){
handlePipeError(err, 'Error piping request to proxy server. Details: ');
})
.pipe(res)
.on('error', function(err){
handlePipeError(err, 'Error piping proxy response to client. Details: ')
});
function handlePipeError(err, customMsg) {
console.log( customMsg, err );
res.writeHead(503, {
'Content-Length': Buffer.byteLength(err.message, 'utf8'),
'Content-Type': 'text/plain' });
res.end(err.message);
}
}
else {
next();
}
There is also some other middleware to handle static file serving and some other stuff. Once all the middleware is setup I start the server like this:
var server = require('http').createServer(app);
server.listen(port)
I would now like to expand this script to allow reverse proxying websocket connections. I tried using the nodejitsu/node-http-proxy to do modify the previous portion of the code like so:
var options = {
ws: true,
target: apiUrl,
secure: false,
xfwd: true
};
var wsProxy = require('http-proxy').createProxyServer(options);
var server = require('http').createServer(app);
server.on('upgrade', function (req, socket, head) {
console.log("--- CAUGHT UPGRADE ----");
wsProxy.ws(req, socket, head);
});
server.listen(port);
I notice the upgrade event fires off and the callback function does run but the websockets request isn't actually working (the client seems to never establish a connection). Is there a better way to achieve this

Resources