I have been struggling trying to deploy a NodeJS server as SocketIO server on Linode. I have deployed my Django projects that works fine and I have redirected a subdomain to talk to the node server listening on port 8002 of local host.
I get a 404 error in my nginx log.
"GET /socket.io/?EIO=3&transport=polling HTTP/1.1" 404 72 "-" "Dalvik/2.1.0 (Linux; U; Android 5.0.1; LG-D850 Build/LRX21Y)"
Here is my nginx config
server {
listen 80;
server_name www.domain.com;
location / {
proxy_pass http://127.0.0.1:8000;
}
location /static {
alias /home/exampledir/staticfiles;
}
access_log /home/exampledir/nginx-access.log;
error_log /home/exampledir/nginx-error.log info;
}
server {
listen 80;
server subdomain.domain.com;
location / {
proxy_pass http://127.0.0.1:8002;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}
Here is my nodejs server file
var socket = require('socket.io');
var express = require('express');
var http = require('http');
var app = express();
var server = http.createServer(app);
server.listen(8002, '127.0.0.1');
var io = socket.listen(server);
var redis = require('redis');
var sub = redis.createClient();
sub.subscribe('notify');
io.on('connection', function(socket){
socket.on('join', function (data) {
...
});
});
//Grab message from Redis and send to client
sub.on('message', function(channel, message){
...
});
I have tried using CORS and stuff but it does not work just keeps giving me a 404. I have verified the node server is running at 127.0.0.1:8002
My android socket is connecting to
mSocket = IO.socket("http://subdomain.domain.com/);
Please help.
Try this config
server {
listen 80;
# Make site accessible from http://localhost/
server_name domain.com;
location / {
proxy_pass http://127.0.0.1:8000;
}
location / {
proxy_pass http://127.0.0.1:8000;
}
location /static {
alias /home/example-dir/staticfiles;
}
access_log /home/example-dir/nginx-access.log;
error_log /home/example-dir/nginx-error.log info;
}
server {
listen 80;
server_name subdomain.domain.com;
location / {
proxy_pass http://127.0.0.1:8002;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}
access_log /home/example-dir/socketnginx-access.log;
error_log /home/example-dir/socketnginx-error.log info;
}
Related
I want to run an express server and a socket.io server on an node.js instance which are reachable through nginx. If possible, I would favor to run them both on the same port, but I did not reach that goal either.
I can reach the webserver locally and from extern.
I can only reach the socket server locally.
When I call the page, my browsers log shows the following error:
GET https://example.com/socket.io/?EIO=3&transport=polling&t=O6qCW5Y
400 Bad Request
So I think the problem lies somewhere in the nginx config.
My app.js code for the socket.io server:
const http = require('http').createServer();
const io = require('socket.io')(http);
http.listen(3001, () => {
console.log('Socket-Server listening on port: 3001');
});
io.on('connection', (socket) => {
...
});
My code for the client:
window.onload = function() {
const socket = io.connect('https://box-api.com/');
socket.on('connect', () => {
...
}
}
My nginx config:
server {
server_name example.com;
root /nodejs/example.com;
include static_files.conf;
index app.js;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
}
location /socket.io {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:3001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
# Certbot stuff
...
}
I have a docker containerized application with react front-end and nodeJS/PHP backend (working on different containers). I've successfully installed https with an intermediate container (let'sencrypt certbot) for my front-end build and PHP backend, but have some problem with socket pooling to nodejs backend. When socket.io pooling starts I got the error on POST request:
[POST] https://my.domain/socket.io/?EIO=3&transport=polling&t=MlE0IBv
405 Not Allowed
When I tried to prevent this by next Nginx construction:
error_page 405 #nodejs;
I got the same error code with the next message:
code: 2 message: "Bad handshake method"
There is part of my Nginx configuration (nginx is separate docker container):
upstream node {
ip_hash;
server node:4000; //nodejs container
}
server {
listen 80;
// ...redirect to https
}
server {
listen 443 ssl;
// .... cert's and other settings
// front-end static react build
location / {
try_files $uri /index.html =404;
}
location /static {
try_files $uri #nodejs;
}
location #nodejs {
proxy_pass http://node;
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;
}
// without this string i just got "405 Not Allowed" nginx error page
// with this string i got probably nodejs "Bad handshake method" error
error_page 405 #nodejs;
}
My app.js server code:
const express = require('express');
const http = require('http');
const socketIO = require('socket.io');
const socketRouter = require('./sockets/index');
const app = express();
const server = http.Server(app);
const io = socketIO(server, {origins: '*:*'});
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
io.on('connection', socketRouter.bind({}, io));
module.exports = server;
And index.js:
require('dotenv').config();
const app = require('./src/app');
const PORT = process.env.APP_PORT || 4000;
app.listen(PORT);
console.log('Application started on Port ' + PORT);
console.log('APP_ENV ' + process.env.APP_ENV);
Problem was solved. The correct config is:
location /static {
try_files $uri =404;
}
location /socket.io {
proxy_pass http://node;
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;
add_header Front-End-Https on;
}
error_page 405 #nodejs;
I have a socket.io webservice running port 8080 on my production server, it responds to http requests, but I think its having difficulty resolving the proxy when my client is sending over websocket protocols (ws://)
My client is telling me that the server is responding with a 400 (bad request) error, so something is either wrong on my client side, or my production server. Im banking on it being my production server, but neither myself or a co worker of mine can figure out where for sure.
These are the nginx configurations we have for our node.js production box.
I have replaced the real url with someapp.com
NGINX
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name app.someapp.com;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_pass http://127.0.0.1:3000;
}
}
server {
listen 8080;
server_name app.someapp.com;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_pass http://127.0.0.1:4000;
}
}
server {
listen 80;
server_name tools.someapp.com;
root /var/www/bbclient/dist;
location / {
try_files $uri $uri/ /index.html;
}
}
its a very small and simple socket.io node.js server running on port 8080 in production
Socket.IO
const app = require('express')()
const http = require('http').Server(app)
const io = require('socket.io')(http)
const bodyParser = require('body-parser')
app.use(bodyParser.urlencoded({ extended: true }))
app.use(bodyParser.json())
// this is not responding from the client
// this is working on localhost, but not in production
io.on('connection', (socket) => {
socket.on('USER_ID', (userId) => {
if (socket.userId) {
socket.leave(socket.userId)
}
socket.userId = userId
socket.join(userId)
})
})
// this works over http, and responds in production
// by visiting http://app.someapp.com:8080 in the browser
app.get('/', (req, res) => {
res.send('some app')
})
http.listen(process.env.PORT || '8888', () => {
console.log('listening')
})
Here is what the network tab is saying about the request coming from my client resulting in a 400 error.
chrome browser network tab
Edit 1
NGINX error logs:
2018/02/06 17:30:39 [error] 5954#5954: *86956 upstream timed out (110: Connection timed out) while reading response header from upstream, client: 76.218.92.156, server: app.someapp.com, request: "GET /socket.io/?EIO=3&transport=polling&t=M5iAdrw&sid=Jays0pqU3StUhdjjAACb HTTP/1.1", upstream: "http://127.0.0.1:4000/socket.io/?EIO=3&transport=polling&t=M5iAdrw&sid=Jays0pqU3StUhdjjAACb", host: "someapp.com:8080", referrer: "http://tools.someapp.com/scorecards/estimating"
First of all add socket.io proxy directives:
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
Here's an example.
Then try to increase proxy connection timeout:
proxy_connect_timeout 75s;
proxy_read_timeout 75s;
proxy_send_timeout 75s;
I am trying to set up my node server that uses express to serve files on port 3000 and the net library to serve a TCP server on port 5052, so:
const express = require('express');
const app = express();
const httpServer = require('http').Server(app);
const io = require('socket.io').listen(httpServer);
const path = require('path');
const net = require('net');
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, './public/index.html'))
});
let server = net.createServer(function(socket) {
// Left out for brevity
}
server.listen(5052, 'localhost');
httpServer.listen(3000, () => {
console.log('Ready on port 3000');
});
Locally, this all works very well. I can load up localhost:3000 and I get my HTML served and it connects to socket.io fine. I can also connect to the server on port 5052 perfectly and life is good. I just can't get nginx to serve it all correctly. Here's what I have:
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name mycoolproject.com www.mycoolproject.com;
location / {
proxy_pass http://localhost:3000;
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;
}
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/mycoolproject.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mycoolproject.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
if ($scheme != "https") {
return 301 https://$host$request_uri;
}
}
server {
listen 5053;
server_name mycoolproject.com www.mycoolproject.com;
location /{
proxy_pass http://localhost:5052;
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;
}
}
When I navigate to mycoolproject.com I get the site loaded fine, so the express side is working fine. I just can't connect to my server on 5053. Any ideas?
You need to configure a different port for Nginx, 5052 is busy by Node.js.
server {
listen 5053;
server_name mycoolproject.com www.mycoolproject.com;
location /{
proxy_pass http://localhost:5052;
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;
}
}
Then you can connect to mycoolproject.com:5053
I have an express app on a single server running behind nginx
I've tested socket.io communication and it runs fine on our dev server.
Adding ssl to the mix yielded the following console log on the client:
As you can notice it produces a 400 (Bad Request) - and then loads the same request successfully, but my console logs are not being run since the connection is not successful...
Would appreciate any feedback. Thanks.
This is the code:
This is my nginx config:
upstream example.com {
server 127.0.0.1:3000;
}
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /path/to/nginx/ssl/example.crt;
ssl_certificate_key /path/to/nginx/ssl/example.key;
location / {
proxy_pass http://example.com;
proxy_redirect off;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_http_version 1.1;
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_set_header X-Forwarded-Proto https;
}
location /public {
root /var/www/example/;
}
location /favicon.ico {
root /var/www/example/public/favicon.ico;
}
}
server {
listen 443 ssl;
server_name www.example.com;
return 301 https://example.com$request_uri;
}
server {
listen 80;
server_name example.com;
return 301 https://example.com$request_uri;
}
server {
listen 80;
server_name www.example.com;
return 301 https://example.com$request_uri;
}
this is my socket.io related code on the express server
var express = require('express');
var app = express();
var http = require('http').Server(app);
var io = require('socket.io')(http);
http.listen(port, function(){
console.log('MyDomain.com app listening at ', 'http://localhost:'+port);
io.on('connection', function(socket){
console.log('socket.io connected','socket.id: '+socket.id);
socket.on('new-user', function(data) {
var user_id = data.user_id;
console.log('new-user, user_id: ', user_id);
});
});
});
this is my client side that tries to connect:
var socket = io.connect(null, { secure: true, port: 443, rememberTransport: false, 'reopen delay': 1000 });
//I have also tried these variations...
//-----------------------------------------
//var socket = io();
//var socket = io.connect('https://localhost', {secure: true});
//var socket = io.connect('https://example.com',{secure: true});
//var socket = io.connect('https://example.com');
//-----------------------------------------
socket.on('connect', function () {
console.log('on "connect"');
socket.emit('new-user', {user_id:some_user_id});
});
on my html template I'm using this to load socket.io
<script src="/socket.io/socket.io.js"></script>
UPDATE 01:
I've noticed that when I go to a different URL in the browser, then come back - the sockets are loading correctly...
Does this indicate a delay which is needed...?