Client unable to hit socket.io server - javascript

Project is hosted on Digital Ocean.
On the client side, its throwing a 404 error
GET http://134.209.147.204/socket.io/?EIO=3&transport=polling&t=NKKWF-X //404
Here is the nginx config file
server {
listen 80;
root /var/www/html;
location / {
proxy_pass http://127.0.0.1:5000; (where the frontend is running)
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location /socket/ {
proxy_pass http://localhost:3001; (where the sockets.io server is running)
}
}
Frontend
socket = io('/socket/')
Both the frontend and backend runs without any errors and can be accessed from the browser.

After days of hacking, I was able to make it work!
nginx config
upstream websocket {
server 127.0.0.1:3001;
}
server {
listen 80;
root /var/www/html;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location /ws/ {
proxy_pass http://websocket/socket.io/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
socket.io server
const app = require('express')();
const server = app.listen(3001);
const io = require('socket.io').listen(server);
socket.io client
socket = io.connect('http://yourdomain/', {path: '/ws/'})

I faced the same problem when trying to connect a sockets.io application to a nodejs server that is behind an Apache2 server. I access the nodejs using /video/. I read this answer and didn't get it. Dummy me! But just in case I'm not alone, I'll attempt to clarify it further here.
I ended up having to follow the code of sockets.io to understand what they mean in the documentation. I'm such a dummy. The documentation says:
A new Socket instance is returned for the namespace specified by the
pathname in the URL, defaulting to /. For example, if the url is
http://localhost/users, a transport connection will be established to
http://localhost and a Socket.IO connection will be established to
/users
After following the code, the meaning (in my dummy's mind) became clear. The socket connection is made with the "String" that I specify in socket=io("url/video/"), but that the transport connection will be attempted to just its "url" part. To change the transport connection path, you need to specify one of the options described in the documentations for the Manager class, which are the same as the options for the io class.
Here is a link to the pertinent documentation, you need to read the io and the Manager headings.

Related

Configuring HTTPS for Express and Nginx

I am trying to configure my ExpressJS app for https connection. The Express server runs at localhost:8080 and the secure one localhost:8443.
Here is the server.js code related to https:
var app = express();
var https = require('https');
const options = {
cert: fs.readFileSync('/etc/letsencrypt/live/fire.mydomain.me/fullchain.pem'),
key: fs.readFileSync('/etc/letsencrypt/live/fire.mydomain.me/privkey.pem')
};
app.listen(8080, console.log("Server running"));
https.createServer(options, app).listen(8443, console.log("Secure server running on port 8443"));
And here is my Nginx configuration:
server {
listen 80;
listen [::]:80;
server_name fire.mydomain.me;
location / {
proxy_pass http://localhost:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
server {
listen 443;
listen [::]:443;
server_name fire.mydomain.me;
location / {
proxy_pass https://localhost:8443;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
What I did :
Generating SSL certificate with Letsencrypt certonly tool for the domain fire.mydomain.me.
Configuring nginx.
Configuring the server.js node app.
Adding TCP rules for the 443 port in Ufw.
I tried
Commenting the not-ssl server line in server.js to force the connections to go through ssl configuration: this serve the page when I try to go to fire.mydomain.me:443 but not to "https:// fire.mydomain.me". In both cases, no SSL. Trying to go to https:// fire.mydomain.me generate this message "This website doensn't provide a secure connection" in Google Chrome.
I followed this tutorial in the first place to set my ssl node config :
https://medium.com/#yash.kulshrestha/using-lets-encrypt-with-express-e069c7abe625#.93jgjlgsc
You don't need to use HTTPS between your nginx reverse proxy and Node app running on the same host. You can proxy both HTTP requests to port 80 and HTTPS requests to port 443 to the same port in your Node app - 8080 in this case - and you don't need to configure TLS certificates in that case.
You can change your server.js file to:
var app = express();
app.listen(8080, console.log("Server running"));
and use an nginx config that has proxy_pass http://localhost:8080; for both HTTP on port 80 and HTTPS on port 443.
This is how it is usually done. Encrypting traffic on the loopback interface doesn't add any security because to sniff the traffic you need root access to the box and when you have it then you can read the certs and decrypt the traffic anyway. Considering the fact that most of the posts on https://nodejs.org/en/blog/vulnerability/ are related to OpenSSL, one could argue that using SSL in Node can make it less secure in that particular case of encrypting loopback interface traffic. See this discussion on the Node project on GitHub for more info.
Thanks to #rsp solution, here is the working Nginx configuration :
server {
listen 80;
listen 443 ssl;
server_name fire.mydomain.me;
ssl_certificate /etc/letsencrypt/live/fire.mydomain.me/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/fire.mydomain.me/privkey.pem;
location / {
proxy_pass http://localhost:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}

Proxy a WS (web socket) connection?

I have a connection to a web socket but it is limited to the intranet.
Looks like this:
socket = new WebSocket("ws://xx.xxx.6.98:8200/demo/");
It it possible to proxy it from the server side so it can become accessible from the outside world?
Something like:
socket = new WebSocket("ws://mysite.com/getWebSocket/demo/");
With Nginx you can forward the traffic towards your destination server. Here is an example of how to proxy forward a Socket.IO Websocket.
location /socket.io/ {
proxy_pass http://xx.xxx.6.98:8200;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
Useful link: https://www.nginx.com/blog/websocket-nginx/
Sure, what I do with SignalR is running it on a server, and expose it to the internet with ProxyPass on Apache.
So what you need is a Reverse Proxy, you can also let it work with Nginx but this is with Apache:
ProxyPass /ws ws://xx.xxx.6.98:8200/demo/
You have this on a domain or server IP, and when you go to ipaddressordomain.com/ws you actually go to ws://xx.xxx.6.98:8200/demo/

http to a Node server over https nginx website

Is it possible to have a http connection to a node.js server over a website which is generally secured by https ?
how do you suggest to combine a node connection with a website that is operating on https .
As already mentioned in the comments, it is useful to create a proxy to your node.js applications.
A good tutorial is, for instance, from DigitalOcean: https://www.digitalocean.com/community/tutorials/how-to-set-up-a-node-js-application-for-production-on-ubuntu-14-04
In this tutorial, it shows that the host configuration can look like this:
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://APP_PRIVATE_IP_ADDRESS:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
In this case, a reverse proxy to the port 8080 was created. Generally, this method can be used for every node.js application.
In your case: add the location block in your https server block and modify the route.
Support for https was just added to node-http-server it can spin up both http and https servers at the same time. It also has some test certs you can use and a cert generation guide for self signing.
note if you want to spin up on port 80 and 443 you'll need to run with sudo
An example for spinning up the same code on both http and https :
var server=require('node-http-server');
server.deploy(
{
port:8000,
root:'~/myApp/',
https:{
privateKey:`/path/to/your/certs/private/server.key`,
certificate:`/path/to/your/certs/server.pub`,
port:4433
}
}
);
Its super simple and has pretty good documentation and several examples in the examples folder.

Meteor WebSocket connection to 'ws://.../websocket' failed: Error during WebSocket handshake: Unexpected response code: 400

I am brand new to things like Meteor.JS, and was wondering about this error. I started the test project (with the button click meter) and it works, but then I go into the console and see
WebSocket connection to 'ws://shibe.ninja/sockjs/243/5gtde_n9/websocket' failed: Error during WebSocket handshake: Unexpected response code: 400
I don't know how to fix it.
Thanks
Maybe a little late but in case you still stuck on this. I got the same issue when deploying the app and using nginx as proxy.
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
Check also the nginx docs here: http://nginx.com/blog/websocket-nginx/
I bumped into this problem myself, but I already had my proxy headers set correctly and it was still not working. But apparently Cloudflare is causing issues. Here is a great article on the subject: https://meteorhacks.com/cloudflare-meets-meteor
As far as I've found, there are three solutions:
Option 1: Use CloudFlare enterprise, which supports sockets.
Option 2: Disable Meteor WebSockets, which will affect your performance as it fallbacks back to use sock.js as a replacment. To do this, just set your meteor environment like this:
export DISABLE_WEBSOCKETS=1
Option 3: In Cloudflare, create a ddp subdomain for the websocket (ddp.yourdomain.com), then disable Cloudflare on the new subdomain. After that set your meteor environment like this:
export DDP_DEFAULT_CONNECTION_URL=http://ddp.example.com
After this my nginx config needed some adjustments, as this has now become a cross-origin (CORS) setup. This is my new nginx config:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80 proxy_protocol;
listen [::]:80 proxy_protocol;
server_name mydomain.com ddp.mydomain.com;
## This allows the CORS setup to work
add_header Access-Control-Allow-Origin 'http://example.com';
## This hides the CORS setup from the Meteor server
## Without this the header is added twice, not sure why?
proxy_hide_header Access-Control-Allow-Origin;
## Idealy the two options above should be disabeled,
## Then use this one instead, but that caused issues in my setup.
# proxy_set_header Access-Control-Allow-Origin 'http://example.com';
location / {
proxy_pass http://localhost:3000;
proxy_set_header Host $host; # pass the host header
proxy_set_header Upgrade $http_upgrade; # allow websockets
proxy_set_header Connection $connection_upgrade;
proxy_set_header X-Real-IP $remote_addr; # Preserve client IP
proxy_set_header X-Forwarded-For $remote_addr;
proxy_http_version 1.1;
# Meteor browser cache settings (the root path should not be cached!)
if ($uri != '/') {
expires 30d;
}
}
}
Finally, remember to restart nginx.

how to install multiple nodejs app with multiple domains?

i read more than ever in this time, this will be my first webpage so i decided mount on nodejs. I make the app very quickly and i test in localhost:9000
so i want to put more apps running on a VPS, i search information and i have two options
first use nginx to proxy the apps...
upstream example1.com {
server 127.0.0.1:3000;
}
server {
listen 80;
server_name www.example1.com;
rewrite ^/(.*) http://example1.com/$1 permanent;
}
# the nginx server instance
server {
listen 80;
server_name example1.com;
access_log /var/log/nginx/example1.com/access.log;
# pass the request to the node.js server with the correct headers and much more can be added, see nginx config options
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://example1.com;
proxy_redirect off;
}
}
i dont understand this config file because i never use nginx so i search a second option
using vhost from expressjs()
express()
.use(express.vhost('m.mysite.com', require('/path/to/m').app))
.use(express.vhost('sync.mysite.com', require('/path/to/sync').app))
.listen(80)
im using expressjs and i understand how to configure, but there are some questions about wich is the best option because using express() i have one app managing multiple apps so i think it is not a good practice and a waste of resources.
from this post, David Ellis says
If you don't need to use WebSockets (or any HTTP 1.1 feature, really), you can use NginX as your proxy instead.
The advantage is the total load NginX can handle versus Node is higher (being statically compiled and specialized for this sort of thing, basically), but you lose the ability to stream any data (sending smaller chunks at a time).
For a smaller site, or if you're unsure what features you'll need in the future, it's probably better to stick with node-http-proxy and only switch to NginX if you can demonstrate the proxy is the bottleneck on your server. Fortunately NginX isn't hard to set up if you do need it later.
and from this post i read an example to configure xginx with many apps but i dont understand how to use that for me
upstream example1.com {
server 127.0.0.1:3000;
}
server {
listen 80;
server_name www.example1.com;
rewrite ^/(.*) http://example1.com/$1 permanent;
}
# the nginx server instance
server {
listen 80;
server_name example1.com;
access_log /var/log/nginx/example1.com/access.log;
# pass the request to the node.js server with the correct headers and much more can be added, see nginx config options
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://example1.com;
proxy_redirect off;
}
}
upstream example2.com {
server 127.0.0.1:1111;
}
server {
listen 80;
server_name www.example2.com;
rewrite ^/(.*) http://example2.com/$1 permanent;
}
# the nginx server instance
server {
listen 80;
server_name example2.com;
access_log /var/log/nginx/example2.com/access.log;
# pass the request to the node.js server with the correct headers and much more can be added, see nginx config options
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://example2.com;
proxy_redirect off;
}
}
so the question is wich is the best option, use nginx or use vhost???
if i have to use nginx there is any tutorial how to configure nginx to serve many apps on node js???
tnx all
your example for Nginx config seems to be what you're looking for. you should create your config files under /etc/nginx/sites-available and then create a symbolic link for those you want to enable to /etc/nginx/sites-enabled
maybe this will help you - http://blog.dealspotapp.com/post/40184153657/node-js-production-deployment-with-nginx-varnish

Categories