I use the following module and it works fine for reverse proxy
https://github.com/nodejitsu/node-http-proxy
currently I've used the code like the following example
httpProxy.createServer({
target: 'ws://localhost:9014',
ws: true
}).listen(8014);
my question is how can I check/simulate that the websockets are working?
Any test will be helpful...
In response to the OP's request for browser test, I modified my original solution to proxy both HTTP and WS traffic to a server where an index.html file is served. This file then connects the browser to the proxy server via WebSocket, which the proxy then proxies to the main server. A simple message is printed on the browser document from the main server.
So that there is no need to copy/paste anything, I created this repo with full instruction: https://github.com/caasjj/httpproxy.git
Here is the code in case others want to look at it here. To run the whole thing, create the two server files and the index.html file, start the servers with node proxyreceiver.js and node proxyserver.js and then navigate to localhost:8014/index.html.
(proxyserver.js):
var httpProxy = require('http-proxy');
var http = require('http');
var proxy = new httpProxy.createProxyServer({
target: {
host: 'localhost',
port: 9014
}
});
var proxyServer = http.createServer(function (req, res) {
proxy.web(req, res);
});
//
// Listen to the `upgrade` event and proxy the
// WebSocket requests as well.
//
proxyServer.on('upgrade', function (req, socket, head) {
proxy.ws(req, socket, head);
});
proxyServer.listen(8014);
(proxyreceiver.js):
var app = require('http').createServer(handler)
var io = require('socket.io')(app);
var fs = require('fs');
app.listen(9014);
function handler (req, res) {
res.writeHead(200);
fs.readFile('index.html', function(err, data){
res.end(data);
})
}
io.on('connection', function (socket) {
socket.emit('data', { message: 'Hello World!' });
socket.on('resp', function(msg) {
console.log('Got message: ', msg);
});
});
(index.html):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Web Socket Proxy Test</title>
<script src="https://cdn.socket.io/socket.io-1.3.5.js"></script>
<script>
var socket = io('http://localhost:8014');
var p = document.createElement("p")
socket.on('data', function (data) {
console.log('Got', data);
p.innerHTML = "Received:" + data.message;
document.body.appendChild(p);
});
</script>
</head>
<body>
<h1>Test ProxyServer</h1>
</body>
</html>
The best way to test is to create a client to connect to it.
there are many ws modules around. Or you can use this: https://www.websocket.org/echo.html just put your url there and test it.
Related
I can't solve this error of socket.io it shows in the console
GET /socket.io/socket.io.js net::ERR_ABORTED 404
Refused to execute script from '/socket.io/socket.io.js' because its MIME type ('text/html') is not executable, and strict MIME type checking is enabled.
Uncaught ReferenceError: io is not defined
at script.js:1:14
I made this with node.js
The files are below (main server file is index.js)
index.js
var express = require("express");
var app = express();
var http = require("http");
var server = http.createServer(app);
var { Server } = require("socket.io");
var io = new Server(server);
app.get("/", (req, res) => {
res.sendFile(__dirname + "/index.html");
});
app.get("/style.css", (req, res) => {
res.sendFile(__dirname + "/style.css");
});
app.get("/script.js", (req, res) => {
res.sendFile(__dirname + "/script.js");
});
io.on("connection", (socket) => {
socket.on("chat message", (msg) => {
io.emit("chat message", msg);
});
});
app.listen(3000);
index.html
<!DOCTYPE html>
<html>
<head>
<title>Test Socket.io</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<center>
<h1>Test</h1>
</center>
<script src="/socket.io/socket.io.js"></script>
<script src="script.js"></script>
</body>
</html>
style.css
body {
font-family: Arial;
}
script.js
var socket = io();
Help will be appreciated.
Replace this:
app.listen(3000);
with this:
server.listen(3000);
app.listen() creates a new server so the server you're starting is NOT the server that socket.io is hooked to, therefore the socket.io library is not hooked up to that server and when the request for /socket.io/socket.io.js comes in, you don't get the socket.io JS library.
Here's the code for app.listen():
app.listen = function listen() {
var server = http.createServer(this);
return server.listen.apply(server, arguments);
};
You can see that it creates a new server and then calls .listen() on that new server.
Your express code works because app is hooked to the server created by app.listen(), but socket.io is hooked to the server created by:
var server = http.createServer(app);
var io = new Server(server);
which is never started and is not running. So, socket.io is never hooked up to the server that is actually running. Instead, you should just create and start one server and hook both app and socket.io to that one server.
I am trying to implement chat application using nodejs and socket.io. The application works on localhost. But when I deploy same on my production server then socket.io can't make any connection.
Code for server.js
var express = require('express');
var app = express();
var socket = require('socket.io');
var chat_controller = require('./controllers/ChatController.js');
var user_controller = require('./controllers/UserController.js');
var Group_controller = require('./controllers/GroupChatController.js');
app.get('/search', function (req, res) {
user_controller.get(req, res);
});
app.get('/groupSearch', function (req, res) {
user_controller.get(req, res);
});
var server = app.listen(3600, function () {
var host = server.address().address
var port = server.address().port
console.log("Example app listening at http://%s:%s", host, port)
});
var io = socket(server);
io.on('connection', (socket) => {
console.log('made socket connection', socket.id);
socket.broadcast.emit('userconnected');
chat_controller.respond(io, socket);
Group_controller.respond(io, socket);
user_controller.respond(io, socket);
});
io.on('disconnect', function () {
console.log('made socket disconnect', socket.id);
});
Code for client.js
var socket = io.connect('https://www.mywebsite.com', {
path: '/apichat'
});
/* Other events related to socket. */
As my server uses SSL I can't used IP:PORT directly so I am using ProxyPass as
ProxyPass /apichat http://127.0.0.1:3600
After all this still socket connection is not established between server and client.
Error shown in browser console is:
POST https://www.mywebsite.com/apichat/?EIO=3&transport=polling&t=MUc-TJK 404 (Not Found)
And in browser Network tab it shows:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error</title>
</head>
<body>
<pre>Cannot POST /</pre>
</body>
</html>
I have checked many other questions posted here and other sites but no question address this issue.
Please Help.
The issue you are encountering is probably due to ssl enabled on your website.
You need to pass ssl related files in your app.js file. Sample code for this is as follow:
var fs = require('fs');
var options = {
key: fs.readFileSync('PATH_TO_SSL_KEYS.key'),
cert: fs.readFileSync('PATH_TO_SSL_CERTS.crt'),
ca: fs.readFileSync('PATH_TO_SSL.pem')
};
var app = require('https').createServer(options, handler), io = require('socket.io').listen(app);
io.set('transports', [
'websocket',
'flashsocket',
'htmlfile',
'xhr-polling',
'jsonp-polling',
'polling'
]);
function handler(req, res) {
res.writeHead(200);
res.end("welcome sir!");
}
var chat_controller = require('./controllers/ChatController.js');
var user_controller = require('./controllers/UserController.js');
io.sockets.on('connection', function (socket) {
socket.broadcast.emit('userconnected');
chat_controller.respond(io, socket);
user_controller.respond(io, socket);
socket.on('message', function (data) {
socket.broadcast.emit('message', data);
});
});
io.on('disconnect', function (socket) {
console.log('made socket disconnect', socket.id);
});
app.listen(3300);
Try editing your application file as per above mentioned sample code and then try to use it. If you can't get path to ssl related file, then you need to contact either your system administrator or the hosting provider.
I hope it helped.
I have just started evaluating the node-http-proxy because I need to have a scalable web socket server.
I have tested the ’simple-balancer-with-websockets’ example provided in the repository but it does not work when acting as a proxy to multiple addresses. It only works as a proxy for one address!
When proxying to multiple addresses a WebSocket hangup error as follows:
Error: socket hang up
at createHangUpError (http.js:1472:15)
at Socket.socketOnEnd [as onend] (http.js:1568:23)
at Socket.g (events.js:180:16)
at Socket.EventEmitter.emit (events.js:117:20)
at _stream_readable.js:920:16
at process._tickCallback (node.js:415:13)
I am using:
node 0.10.26
socket io 1.0.6
node-http-proxy 1.1.5
platform OSX
The following is the load-balancer. Its only difference to the provided sample is the addresses used and the listen port.
var http = require('http'),
httpProxy = require('http-proxy');
//
// A simple round-robin load balancing strategy.
//
// First, list the servers you want to use in your rotation.
//
var addresses = [
{
host: 'localhost',
port: 8000
},
{
host: 'localhost',
port: 8001
},
{
host: 'localhost',
port: 8002
}
];
//
// Create a HttpProxy object for each target
//
var proxies = addresses.map(function (target) {
return new httpProxy.createProxyServer({
target: target
});
});
//
// Get the proxy at the front of the array, put it at the end and return it
// If you want a fancier balancer, put your code here
//
function nextProxy() {
var proxy = proxies.shift();
proxies.push(proxy);
return proxy;
}
//
// Get the 'next' proxy and send the http request
//
var server = http.createServer(function (req, res) {
nextProxy().web(req, res);
});
//
// Get the 'next' proxy and send the upgrade request
//
server.on('upgrade', function (req, socket, head) {
nextProxy().ws(req, socket, head);
});
server.listen(9000);
The basic http server acting as a target for the above load-balancer is:
var http = require('http'),
fs = require('fs'),
io = require('socket.io');
var args = process.argv.splice(2);
var port = args[0] || 8000;
server = http.createServer(function(req, res) {
var filePath = (__dirname + '/public/connect.html');
fs.readFile(filePath,function (err, data){
res.writeHead(200, {'Content-Type': 'text/html','Content-Length':data.length});
res.write(data);
res.end();
});
});
server.listen(port, function() {
console.log('ws listening on: ' + port);
});
io = io(server);
io.on('connect', function(socket){
console.log('socket connected');
socket.emit('message', 'ws message from ' + port);
});
The client html is:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io();
socket.on('message', function (data) {
console.log(data);
});
</script>
</head>
<body>
node-http-proxy basic load balance test with websockets
</body>
</html>
I regard this as a basic test and yet it does not work! Can anyone explain what I am doing wrong and suggest a solution please?
Many thanks for any thoughts.
Socket.io 1.0 needs sticky sessions. See socket.io/docs/using-multiple-nodes
First engine.io makes an xhr request then it makes an websocket request. Both requests need to reach the same socket.io server. Even more so if engine.io needs to fallback to long polling etc . . .
To fix it, you just need to make your proxy server session aware. It can still round robin fresh connections, but as soon as it serves a socket.io request it needs to route subsequent requests from that session to the same backend.
Does anyone has experience to have Node.js and socket.io working on Cloud9 IDE?
The "Example (NodeJS with Socket.io)" (at https://c9.io/site/blog/2013/05/native-websockets-support/) doesn't work.
First, the server (https://c9.io/etlolap/webapp, /test.js) throws an error unless I fix as follow. I clicked Run button while test.js is on active tab.
var
socketIo = require('socket.io'),
io = socketIo.listen(Number(process.env.PORT));
io.sockets.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});
Then, my client (https://c9.io/etlolap/webapp, /test.html) still cannot connect. I clicked Preview button while test.html is on active tab.
<!doctype html>
<html>
<head>
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('https://webapp-c9-etlolap.c9.io');
socket.on('news', function (data) {
console.log(data);
socket.emit('my other event', { my: 'data' });
});
</script>
</head>
<body>
Loading...
</body>
</html>
and got error message below.
Failed to load resource: the server responded with a status of 404 --- (Not Found) https://c9.io/socket.io/socket.io.js
Uncaught ReferenceError: io is not defined --- test.html:6
1. Steps
1.1) Run server.js
The cloud 9 console shows up:
1.2) Hit Preview on index.html
1.3) Then a window is opening on the right side of your IDE. You can either hit the button in the middle of the navigation bar or copy and paste the url into a new browser window.
1.4) Socket communication is working!
2. Prerequisite
2.1) node module socket.io
Hit F6 or View -> Console and install socket.io.
2.2) the client side JavaScript from socket.io
Since I didn't find an official link to download it, I created a GitHubGist.
socket.io.js
3. Code
server.js
// module dependencies
var http = require("http"),
sio = require("socket.io");
// create http server
var server = http.createServer().listen(process.env.PORT, process.env.IP),
// create socket server
io = sio.listen(server);
// set socket.io debugging
io.set('log level', 1);
io.sockets.on('connection', function (socket) {
socket.emit('news', { message: 'Hello world!' });
socket.on('my other event', function (data) {
console.log(data.message);
});
});
index.html
<!DOCTYPE html>
<html>
<script src="js/socket.io.js"></script>
<script>
var socket = io.connect("https://demo-project-c9-matthiasholdorf.c9.io");
socket.on("news", function(data) {
console.log(data.message);
});
socket.emit("my other event", { message : "client emit" } );
</script>
</html>
Thanks for feedback from damphat and Matthias. After many failed attempts, finally I figured out the solution myself.
On Cloud9 IDE, the typical line in client (test.html here) has to be changed from,
<script src="/socket.io/socket.io.js"></script>
to
<script src="https://webapp-c9-etlolap.c9.io/socket.io/socket.io.js"></script>
The prefix is the URL of your Cloud9 project URL. By changing this line, my example worked.
you must flowing these step:
open the terminal on https://c9.io/etlolap/webapp, type:
npm install socket.io
node test
then open a new tab of browser with url
https://webapp-c9-etlolap.c9.io/socket.io/socket.io.js
You will see socket.io.js source code
I did not how you open test.html in c9.io without http server, did you just press preview?
Edit:
To return html files, you should merge http server and socket.io server like this:
// file: test.js
var app = require('http').createServer(handler)
, io = require('socket.io').listen(app)
, fs = require('fs')
app.listen( Number( process.env.PORT ) );
function handler (req, res) {
fs.readFile(__dirname + '/test.html',
function (err, data) {
if (err) {
res.writeHead(500);
return res.end('Error loading index.html');
}
res.writeHead(200);
res.end(data);
});
}
io.sockets.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});
To fetch any html file requested, using html files located in the file folder, you can use express:
var fs = require('fs');
var express = require('express');
var app = express();
// This fetches html files from the client folder (if they exist), and returns a "Page could not be found" error otherwise (this can be customized to some other 404 error page as desired)
app.get('*', function (req, res) {
var urlReading = req.url;
if (urlReading == "/")
{
urlReading = "/index.html";
}
urlReading = __dirname + "/client" + urlReading;
console.log("Loading: " + urlReading);
fs.readFile(urlReading, function (err, html) {
if (err) {
console.log("Could not find " + urlReading)
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end("<html><head><title>Page could not be found</title></head><body><h1>Page could not be found</h1></body></html>");
}
else
{
console.log("Found " + urlReading)
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end(html);
}
});
});
app.listen(process.env.PORT, process.env.IP);
I’m having a problem getting started with Node.js.
I’ve created a basic server that I know works, because if I navigate to http://localhost:5000 in my browser I get the expected message. However, I’m having trouble then connecting to this server on the client side with a basic HTML page.
My Node.js app looks like this:
var http = require('http');
var socket = require('socket.io');
var port = process.env.PORT || 5000;
var players;
var app = http.createServer(function(request, response) {
response.write('Server listening to port: ' + port);
response.end();
}).listen(port);
var io = socket.listen(app);
function init() {
io.configure(function() {
io.set('transports', [ 'xhr-polling' ]);
io.set('polling duration', 10);
});
io.sockets.on('connection', onSocketConnection);
};
function onSocketConnection(client) {
console.log('New connection');
console.log(client);
};
init();
My HTML page looks like this (based on https://github.com/mongolab/tractorpush-server/blob/master/index.html):
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
</head>
<body>
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('/');
socket.on('all', function(data) {
console.log(data);
});
socket.on('complex', function(data) {
console.log(data);
});
</script>
</body>
</html>
I understand that the sockets.io.js file is automatically generated by socket.io, but I just get the following error when I view my index.html file:
Uncaught ReferenceError: io is not defined
How do I actually connect to my server?