socket.io cannot communicate with back-end through express - node.js

I am using socket.io for fetching some data from the express app. Everything works fine on localhost:8080 but when i deploy my code to the server, client side socket.io cannot communicate with back-end socket.io through express server. I've an apache on the server that forwards everything to localhost:8080 including domain.com/socket.io/?transform=polling... and it extends the request to the express server but express returns a 404 (it comes from the express, not from apache). I am out of ideas, what could be the problem? Here is my code:
express = require "express"
jade = require "jade"
fs = require "fs"
class Bootstrap
_self = undefined
routes:
DEFAULT_PATH: "/"
TEMPLATE_PATH: "/load/:view"
DIRECTIVE_PATH: "/directive/:template"
options:
templatePath: "#{__dirname}/../src/templates"
isDev: "#{__dirname}/../dev"
contentPath: "#{__dirname}/../frontend"
libraryPath: "#{__dirname}/../bower_components"
port: 8080
status:
notFound: 404
isDev: undefined
constructor: ->
_self = #
#isDev = fs.existsSync #options.isDev
#app = express()
#app.use "/frontend", express.static(#options.contentPath)
#app.use "/bower_components", express.static(#options.libraryPath)
#app.set "views", #options.templatePath
#app.set "view engine", "jade"
#app.engine "jade", jade.__express
#app.get #routes.DEFAULT_PATH, (request, response)->
appData =
data:
isDev: _self.isDev
response.render "index", appData
#app.get #routes.TEMPLATE_PATH, (request, response)->
view = request.param "view"
response.render view
#app.get #routes.DIRECTIVE_PATH, (request, response)->
template = request.param("template").replace ".html", ""
response.render "directives/"+template
#app.use (request, response, next)->
_self.logger.warning "404 Not Found!: " + request.originalUrl
response.status(_self.options.status.notFound)
appData =
data:
isDev : _self.isDev
request: request
response.render "404", appData
#server = #app.listen #options.port
#io = require("socket.io").listen #server
#logger = require("./logger.js")
#logger.init #isDev
#socketConnector = require("./live.js")
#socketConnector.init #io
#
new Bootstrap()
You can find the entire code here: https://github.com/eyurdakul/ejder.be

Since you specifically said it works locally and I don't see anything special in your code, I really think the issue resides in your Apache config.
There is a module called mod_proxy_wstunnel you need to have and enable in order to get your WebSocket traffic to work and get proxied correctly to your express application. Either you have Apache 2.4 or, you'll need to apply this patch found in this blogpost and compile again. There is also another blog detailing step by step what you should do under Ubuntu.
After making sure you have the module and its loaded, you'll have to tweak your config to add some WebSocket proxying using the ProxyPass directive
ProxyRequests Off
ProxyPass "/socket-io/" "ws://localhost:8080/socket.io/"
ProxyPassReverse "/socket-io/" "ws://localhost:8080/socket.io/"
You might also want to try to use a rewrite condition on the Upgrade header that is sent with WebSockets:
RewriteEngine On
RewriteCond %{HTTP:Connection} Upgrade [NC]
RewriteRule /(.*) ws://localhost:8000/$1 [P,L]
ProxyPass / http://localhost:8000/
has seen in this comment or this specific thread in general, which exposes a few other possible solutions you can try.

A debugging step that you should take is to have a mock client run in your express app and try to connect to the server port using localhost, or whatever the loopback IP address is. In other words (purely as a temporary testing tool) you place a socket.io Node client into your Express app that gets instantiated and immediately tries to connect to the Socket.io server (which is also in the express app). This should work.
If it does work, you've established that your express server is not the problem. Then, on the client you just added to your express app, you should change the connection address from the local IP to the actual IP address of the server.
If it doesn't work, your problem is probably server side.
My guess is that your apache server is forwarding the polling requests properly, but when Socket.io tries to make the handoff to websockets, Apache is denying the WS request and socket.io is handling this denial internally -- which is why the 404 seems to come from express.

Even I had same issue. The port on which the server is listening , is that open on server. As on local all the ports are open but on server , it's not the case.

Related

Namecheap: Node JS Express App - App Route return 404 not found

Trying to get Simple Express Application up using NameCheap Shared Hosting.
I have set up my Node JS application as Described here NodeJS NameCheap Docs
Current Setup:
Application Root: url.com
Application URL: url.com
Application Startup File: server.js
I have ran NPM Install using the button provided
I have tried loading the URL http://url.com/hello Expecting Hello World to displayed in the Page.
var express = require("express");
var app = express();
const port = 3001;
app.set("port", port);
app.get("/hello", function(req, res) {
res.send("hello world");
});
app.listen(app.get("port"), () =>
console.log("Started listening on %s", app.get("port"))
);
The results I am getting when navigating to http://url.com/hello:
Not Found
The requested URL /index.php was not found on this server.
Additionally, a 404 Not Found error was encountered while trying to use an ErrorDocument to handle the request.
Namecheap only tells you how to configure the nodejs app however their hosting is based on cPanel which requires you configure the webserver (apache generally). Once you get an application running there’s a special button to register it for the apache configuration aka let it run from your domain. I don’t know the steps by heart but you should ask NC support to direct you to their documentation for configuring apache to run a nodejs app you configured.
If they do not link an article from their knowledge base use this link: https://confluence1.cpanel.net/plugins/servlet/mobile?contentId=17190639#content/view/17190639
Basically what you need now is to configure cPanel or ssh into your server and test your app locally. There’s a number of things that could cause your issues like incorrect apache configuration (your default port 80 is looking for php app), port not open/firewalled, application not registered - and all of this is cPanel specific.
To make sure you are reading the correct document check in namecheap cpanel for the docs button and review all the above. It should be obvious what needs configured - your nodejs code is probably not the cause here
In my case, it was the problem with .htaccess file. Adding the following rules in my .htaccess file present in the website's public directory helped me:
# CLOUDLINUX PASSENGER CONFIGURATION BEGIN
PassengerAppRoot "/home/<user>/<your_nodejs_app_folder>"
PassengerBaseURI "/."
PassengerNodejs "/home/<user>/nodevenv/<nodejs_app>/<version>/bin/node"
PassengerAppType node
PassengerStartupFile <startup_script>.js
# CLOUDLINUX PASSENGER CONFIGURATION END
Make the required changes in the above rules before pasting them in your .htaccess file. Also, just in case, make sure the port you are using is open, via customer support.

Can't access Node.js server on web server

I'm trying to test a simple Node.js server on my webserver. The problem is that I can't access the Node.js server from my chrome browser and I have searched without any success.
This is my basic server.js script (server side)
var app = require('express')();
app.get('/test', function (req, res) {
console.log('web page opened');
});
app.listen(3000, function () {
console.log('Listening on port 3000');
});
When I run the node in console I get result as expected
public_html$ node server.js
Listening on port 3000
Now when I try to access the URL like this:
http://xxx.xxx.xxx.xxx:3000/test the connection times out and I do not get anything.
This prevents me from using $.ajax form to send data to my node server and the jquery request fails with error as connection timed out issue as well because the URL:3000 with my nodejs port is not accessible.
It seems like my host (Cloudways) does not allow access on any port. If that is case, what can I do really in this situation?
Note: I do not have root access to the server, they can't give root access for security.
Actually going thru Apache to access your app server, nodeJs in your case, is the standard way to avoid security vulnerabilities etc.. You can configure your Apache server as follows:
<VirtualHost *:80>
ProxyPreserveHost On
ProxyRequests Off
ServerName www.example.com
ServerAlias example.com
ProxyPass / http://localhost:3000/test/
ProxyPassReverse / http://localhost:3000/test/
</VirtualHost>
The you would call your app at http://xxx.xxx.xxx.xxx:80/test or simply at http://xxx.xxx.xxx.xxx/test since 80 is implied for HTTP and apache will call http://xxx.xxx.xxx.xxx:3000/test for you.
EDITED: This should work thru .htacccess too - which is what, it seems cloudways wants you to do : https://support.cloudways.com/what-can-i-do-with-an-htaccess-file/
Best way to test node.js is to use node process manager on your server like https://www.npmjs.com/package/pm2.
This will save a lot of time for deployment. but you will need root access to install this package. if you does not have root access then ask your hosting provider to DO install these packages for you.
If in any case you did not get root access and you have no access to open port and install packages for your project. Then use any other hosting like https://www.linode.com/.

Remove Port From Socket.IO and Change Directory

Using Apache on Ubuntu 15.04 I'm trying to effectively remove the port 3000 from the URL as well as to change the path to http://example.com/{app}/socket.io...
Using ProxyPass and ProxyPassReverse I've removed the port from the URL effectively as well as to update the server and client side accordingly to change the path.
Virtual Hosts changes:
ProxyPass /path/ http://example.com:3000/path/
ProxyPassReverse /path/ http://example.com:3000/path/
The server side changes that I made was the following:
var io = require('socket.io')(http, {path: '/path/socket.io' });
app.get('/path/', function(req, res){
and the client changes that I made was the following:
var socket = io({path: '/path/'});
Everything appeared to run smoothly until I opened up my console log and saw a plethora of GET requests while using chrome. This'll definitely kill my bandwith and I guess I somehow managed to not listen to the socket correctly which resulted in the mass amount of GET requests.
Could someone provide some guidance into what I may possibly be doing wrong?
You're seeing a large number of requests as socket.io is falling back to long polling as Apache is not proxying the websocket connection you'll need to enable this with
mod_proxy_wstunnel
then add
ProxyPass "/path/socker.io" "ws://localhost:3000/"

443 apache SSL Port and 8888 https listening Port doesn't work - Node.js - socket.io

currently i have the following problem:
i have an apache server, running SSL on Port 443 and standard (http) on 80.
Additionally a installed a Node.js server with socket.io module.
I wrote an socket.io javascript with a http server that listened to the port 3000, so in the client (browser) i include the socket.io.js like this
<script type="text/javascript" src="http://www.example.com:3000/socket.io/socket.io.js"></script>
This works very fine, when i execute my site via http://www.example.com . The browser finds the socket.io.js properly.
If i execute my site via https like https://www.example.com , i adjust the script part above like this:
<script type="text/javascript" src="https://www.example.com:8888/socket.io/socket.io.js"></script>
I changed the src to https:// and the port to 8888. Now i have to adapt my socket.io script also.
var https = require('https');
var fs = require('fs');
var socketio = require('socket.io');
// The server options
var svrPort = 8888; // This is the port of service
var svrOptions = {
key: fs.readFileSync('/path/to/example.key'),
cert: fs.readFileSync('/path/to/example-ca.crt'),
ca: fs.readFileSync('/path/to/example-server.pem')
};
// Create a Basic server and response
var servidor = https.createServer( svrOptions , function( req , res ){
res.writeHead(200);
res.end('Hi! Code here...');
});
// Create the Socket.io Server over the HTTPS Server
io = socketio.listen( servidor );
// Now listen in the specified Port
servidor.listen( svrPort );
If i execute the file with node, the socket.io started properly:
info - socket.io started
But here comes the problem: if i execute the URL of the socket.io.js file in the browser, nothing happens:
https://www.example.com:8888/socket.io/socket.io.js
Firefox answers with: data communication interrupted
The node server also gets no requests. socket.io doesn't react.
What i have to do?
Thx!
There are two js scripts needed here, one for the node.js server (I assume that is the one you posted) and one embedded in the html page.
The <source> Tag has nothing to do with the execution of your node.js server script. It states where the client will download the client js script, when loading your HTML page. It therefore needs to be downloadable from your browser - just try entering that URL yourself.
The address, where the client side of the socket.io code is receiving its content (the address of the node.js Server) must be updated in the client side js.
Depending on the size of your project, why not also use node.js as the only server for the static content?

Running a forward proxy server in nodejitsu using node js

I am new to proxy server. What I want to do is: I want to write some node.js code, and then upload to my nodejitsu account to run as a proxy server. Then I would like to use my nodejitsu proxy server on my computer, by configuring the http proxy as "abc.jit.su" (my jitsu URL), and the port as "80" in Chrome, Firefox or IE. That's to say, I want my nodejitsu proxy server to have the same function as the proxies listed here: http://www.freeproxylists.net/. Any ideas?
You can write a simple proxy using the request module, like this:
var http = require('http'),
request = require('request');
// For nodejitsu, this will be port 80 externally
var port = process.env.PORT || 8000;
http.createServer(function(req,res) {
req.pipe(request(req.url)).pipe(res)
}).listen(port);
However, this will only work with http, not https.
Nodejitsu also produces a proxy module, you may get some ideas on what to do next by looking at that.

Resources