Socket.io/WebSockets continuously reconnecting — issue with Nginx proxy configuration? - sockets

I am using Socket.IO in my Node.js application. Today I deployed it for the first time, and I noticed that my sockets keep reconnecting. I have "connect" and "disconnect" logging to the console in the respective socket events, and this is the result:
What's more, it seems that the polling technique is being used, when my browser is surely modern enough to use WebSockets — so I believe this is a configuration issue. WebSockets work fine when I am running the Node.js in development with no proxy in the middle.
This is my Nginx configuration, which serves as a proxy to my Node.js server:
upstream reader.oliverjash.me {
server 127.0.0.1:3000;
}
server {
listen 80;
server_name reader.oliverjash.me;
access_log /var/log/nginx/reader.oliverjash.me.access.log;
error_log /var/log/nginx/reader.oliverjash.me.error.log;
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_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass http://reader.oliverjash.me;
proxy_redirect off;
}
}
I believe that the lines:
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
are significant in enabling WebSockets (as per this reference/tutorial). Before I added these, WebSockets did not work at all with the proxy. Now I seem to get polling, which is better than nothing.
My Nginx version is 1.4.0 stable.

Turns out the problem was because I had clustered my Node apps. Added Redis as a memory store for Socket.IO and that solved all of my problems! http://adamnengland.wordpress.com/2013/01/30/node-js-cluster-with-socket-io-and-express-3/

Related

Running a proxy_pass on a subpath in NGINX

I am trying to run a Flask app on Gunicorn through an Nginx server. I would like the app to run on a sub-directory instead of through a different port, if possible, but all I get are 404 errors. Here is my conf file, which is an included file in the conf.d folder:
server {
listen 80;
server_name 127.0.0.1;
location / {
root /var/www/html;
}
location /chess/ {
proxy_pass http://unix:/usr/share/nginx/sockets/chess.sock;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Could someone please tell me how to do this? I have looked all over and tried a lot of different things, to no avail. It runs fine on a different port, but that is not what I want. A subdomain is also a suitable option, but I can only get that to work in production, not development, for some reason. Someone posed the question here but the link they gave to the solution is dead.
when do you get 404's? when you access /chess/?
please attach the flask app's code.
anyway,
the following certainly works, I tested it.
followed this guide
myproject.py:
from flask import Flask
app = Flask(__name__)
#app.route("/chess/",defaults={'name': None})
#app.route("/chess/<name>")
def hello(name):
if name is None:
name="!"
else:
name = ", " + name
# PLEASE don't use the following line of code in a real app, it creates a self-xss vulnerability. ALWAYS sanitize user input.
return f"<h1 style='color:blue'>Hello There{name}</h1>"
if __name__ == "__main__":
app.run(host='0.0.0.0')
nginx - /etc/nginx/sites-enabled/myproject (symlink)
server {
listen 8080;
server_name your_domain www.your_domain;
location / {
root /home/username/myproject/static/;
}
location /chess/ {
include proxy_params;
proxy_pass http://unix:/home/username/myproject/myproject.sock;
}
}
<host>:8080/chess/stackoverflow:
<host>:8080/a.html: (actually served from /home/myproject/static)
generally and for future reference - try looking at nginx logs (/var/log/nginx) or service logs (journalctl -u myproject or systemctl status myproject)
Two methods are available. The first method involves adding the subpath to both the NGINX configuration and the Flask app, as suggested in the answer by Yarin_007. Set up NGINX like so:
server {
listen localhost:80;
location / {
root /var/www/html;
}
location /chess/ {
proxy_pass http://unix:/usr/share/nginx/sockets/chess.sock;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
And alter the Flask app to include the subpath:
from flask import Flask, request
...
#app.route("/chess/", methods=["GET", "POST"])
...
The alternative, as suggested in this answer is to run the Gunicorn service on a non-privileged port (or maybe a subdomain) and use two proxy_pass directives to direct from the port 80 subpath like so:
server {
listen localhost:80;
location / {
root /var/www/html;
}
location /chess/ {
proxy_pass http://localhost:8080/;
}
}
server {
listen localhost:8080;
location / {
proxy_pass http://unix:/usr/share/nginx/sockets/chess.sock;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
The Flask app can remain as it was originally:
from flask import Flask, request
...
#app.route("/", methods=["GET", "POST"])
...

Flutter app cannot make socket connection with certificate handshake error CERTIFICATE_VERIFY_FAILED

One might say this question is a duplicate, but it is not, as other questions this type are about self-signed certificate, and about development environment.
I have a valid certificate from letsencrypt.org, but I cannot manage to establish socket connection. I have a nodejs server where I use the module "ws", and use the package "web_socket_channel" in flutter.
I had the same handshake problem for all my http requests (using requests package) but I could bypass it adding option verify to false:
final r = await Requests.get(app_url, verify: false);
I don't like this solution as it is not secure for production environment.
I would like a solution that would suit production environment.
Thanks to you all
For every one reading this, the problem was not from my flutter code, it was from my nginx configuration, I had to add the following lines to
/etc/nginx/conf.d/sysmon.conf file:
location / {
proxy_set_header X-Forwarded-For $remote_addr;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_pass http://<SERVER_IP>:<PORT>;
}

prevent redirecting to https and URI hacks nginx reverse proxy

I have setted up a reverse proxy on my server with nginx inside docker, and since then all request are redirecting to https although i didn't set all locations to https redirection.
Basically what i want is to be able to serve both https and http with the reverse proxy.
In addition i want to be able to redirect to different URI dynamically, for example i want to set all routes of /bla2/foo/bar to be redirected to only what comes after /bla2
what i tried to get here is that whenever accessing to example.com/bla2/foo/bar it should redirect it to example.com/foo/bar without the bla2 section...
Is it possible on the same configuration file?
what can cause my server to redirect all request to https
This is my server nginx.conf
server {
listen 443;
ssl on;
ssl_certificate /etc/ssl/example.com.crt;
ssl_certificate_key /etc/ssl/example.com.key;
listen 80;
server_name example.com;
location /bla/bla {
proxy_pass http://example.com:3980/foo/bar1;
}
**location /bla2/**{
# proxy_pass http://example.com:3004;
return 301 http://example.com:3004$request_uri;
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_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Forwarded-Proto $scheme;
}
location /app3 {
rewrite ^/app3(.*) /$1 break;
proxy_pass http://example.com:1236/app3;
}
}
I want to be able to get directly content of http://example.com:3004 if i put it in the browser without any redirection to https.
Only if i try access example.com/bla2 i want it to be required https instead of http, and to be redirected to different path.
You need to use regular expression and capture groups for this
location ~* /bla2/(.*) {
return 301 http://example.com:3004$1$is_args$args;
}
Another way of doing it would be just use rewrite
rewrite ^/bla2/(.*)$ http://example.com:3004/$1 redirect;
If you want to transparently proxy it to the example.com:3004 removing /bla2 then you should use
location /bla2/ {
proxy_pass http://example.com:3004/;
}
The trailing slash / in /bla2/ and http://example.com:3004/ is very important here

How to setup Mojolicious with nginx?

Required to develop a web application using Mojolicious. Therefore required to setup with a web server.
From the Mojolicious Nginx documentation:
One of the most popular setups these days is Hypnotoad behind an Nginx reverse proxy, which even supports WebSockets in newer versions.
upstream myapp {
server 127.0.0.1:8080;
}
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://myapp;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Ad:
Required to develop a web application using Mojolicious. Therefore
required to setup with a web server.
isn't true. Just follow the: http://www.mojolicious.org
put into some file, let say: mojo.pl
use Mojolicious::Lite;
get '/' => {text => 'I ♥ Mojolicious!'};
app->start;
To run this example with the built-in development web server start it with morbo.
$ morbo mojo.pl
it will answer:
Server available at http://127.0.0.1:3000
Just CLICK THIS LINK in your browser. You will get
I ♥ Mojolicious!
And could start the development immediatelly. Setting the nginx is enough much-much later - for the deployment.

Nginx site configuration disabling 301 rewrite for another site

I currently have two enabled site configurations in nginx, let us call them old-site.example and new-site.example. There is no other site configuration active.
old-site.example should 301-redirect to new-site.example. This currently works well as long as the old-site.example configuration is alone. After adding the new-site.example configuration file, it does not redirect anymore.
oldsite.conf:
server {
listen 80;
server_name *.old-site.example;
rewrite_log on;
location / {
return 301 http://www.new-site.example$request_uri;
}
}
newsite.conf:
server {
listen 80;
server_name www.new-site.example;
charset utf-8;
location / {
#forward to application server
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:8080;
}
}
other configuration details:
JBoss AS7 as application server running behind Nginx 1.5.1
This was a DNS related error, sorry everyone.
Background: The ISP of the client managed to "smart redirect" the domain instead of using DNS. They basically scraped the new site on their servers and returned it via the old domain. I'm speechless.
If you ever have a problem like this, check DNS resolution before second-guessing your config.