I am trying to set up a websocket call from my Javascript app (running on a public IP address) to my NodeJS server.
For this I am using pm2 and nginx for the server routing, however I believe that I am doing something wrong, as I am unable to get the server to write any of the websocket call into the log, despite the websocket receiving a 200 return message.
The log does write down the starting information, such as which port each thing is starting on, but after that nothing.
My file in /etc/nginx/sites-available/my_app.com (this file is also soft linked to /etc/nginx/sites-enabled):
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
upstream websocket {
server localhost:3010;
}
upstream backend {
server localhost:3000;
}
server {
listen 80;
listen [::]:80;
server_name my_app.com www.my_app.com --My website ip address for testing--;
# these are allowed to use unsecured connection...
location / { proxy_pass http://backend; }
location /ws {
proxy_pass http://websocket;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
}
}
On my server I have the following files: app.js
const express = require("express" )
const http = require("http" )
const { log } = require("./system/global" )
const app = express()
const http_server = http.createServer(app)
const PORT = 3000
require("./system/serve_path")(http_server, 'frontend', app, express)
require("./system/serve_socket").start(PORT)
http_server.listen(PORT, ()=> log("Listening on port " + PORT))
./system/globals.js
const fs = require('fs')
exports.log = (msg) => {
let now = new Date().toISOString()
let log_msg = `${now}: ${msg}`
console.log(log_msg)
let log_folder = './logs'
if (!fs.existsSync(log_folder)) { fs.mkdirSync(log_folder) }
let log_file = `${log_folder}/log.log`
if (!fs.existsSync(log_file)) {
fs.writeFileSync(log_file, '')
} else {
let stats = fs.statSync(log_file)
let fileSize = stats.size
if (fileSize > 1073741824) {
let now = new Date().toISOString()
let new_file_name = `${log_folder}/log_${now}.log`
fs.renameSync(log_file, new_file_name)
fs.writeFileSync(log_file, '')
}
}
fs.appendFile(log_file, '\n' + log_msg, (err) => {
if (err) { console.log(err) }
})
}
exports.load_system = (module_name) => {
return require(`./system/${module_name}`)
}
exports.load_socket = (module_name) => {
return require(`./socket/${module_name}`)
}
./system/serve_path.js
module.exports = (server, path, app, express) => {
app.use(express.static(path))
}
./system/serve_socket.js
const websocket = require('ws')
const { log } = require('./global')
exports.start = (port) => {
let socket_port = port + 10
log("Socket started on port: " + socket_port)
let wss = new websocket.Server({port: socket_port})
wss.on('connection', function(ws) {
log('Socket connected')
ws.on('open', on_message)
ws.on('error', on_message)
ws.on('message', on_message)
})
}
const on_message = (msg) => {
console.log('Received from client: %s', msg);
log('Socket Message: %s', msg);
ws.send('Socket Message: ' + msg);
}
const on_error = (err) => { log('Socket Error: %s', err); }
const on_open = () => { log('Socket connection opened'); }
Your nginx configuration is the problem, you have to put location /
after location /
otherwise it will catch every route, Digital Ocean wrote a good article about this.