I combined the answer above with certbot SSL cert and CORS access-control-allow-headers and got it working so I thought I would share the results.
Apache httpd.conf added to the bottom of the file:
LoadModule proxy_module modules/mod_proxy.so LoadModule proxy_http_module modules/mod_proxy_http.so
Apache VirtualHost settings (doc root for PHP is under Apache and SSL with Certbot, while node.js/socket.io site runs on port 3000 - and uses SSL cert from Apache) Also notice the node.js site uses the proxy for the folder /nodejs, socket.io, and ws (websockets):
<IfModule mod_ssl.c> <VirtualHost *:443> ServerName www.example.com ServerAlias www.example.com DocumentRoot /var/html/www.example.com ErrorLog /var/html/log/error.log CustomLog /var/html/log/requests.log combined SSLCertificateFile /etc/letsencrypt/live/www.example.com/fullchain.pem SSLCertificateKeyFile /etc/letsencrypt/live/www.example.com/privkey.pem Include /etc/letsencrypt/options-ssl-apache.conf RewriteEngine On RewriteCond %{REQUEST_URI} ^socket.io [NC] RewriteCond %{QUERY_STRING} transport=websocket [NC] RewriteRule /{.*} ws://localhost:3000/$1 [P,L] RewriteCond %{HTTP:Connection} Upgrade [NC] RewriteRule /(.*) ws://localhost:3000/$1 [P,L] ProxyPass /nodejs http://localhost:3000/ ProxyPassReverse /nodejs http://localhost:3000/ ProxyPass /socket.io http://localhost:3000/socket.io ProxyPassReverse /socket.io http://localhost:3000/socket.io ProxyPass /socket.io ws://localhost:3000/socket.io ProxyPassReverse /socket.io ws://localhost:3000/socket.io </VirtualHost> </IfModule>
Then my node.js app (app.js):
var express = require('express'); var app = express(); app.use(function(req, res, next) { res.header("Access-Control-Allow-Origin", "*"); res.header("Access-Control-Allow-Headers", "X-Requested-With"); res.header("Access-Control-Allow-Headers", "Content-Type"); res.header("Access-Control-Allow-Methods", "PUT, GET, POST, DELETE, OPTIONS"); next(); }); var http = require('http').Server(app); var io = require('socket.io')(http); http.listen({host:'0.0.0.0',port:3000});
I force a ip4 listener, but that is optional - you can substitute:
http.listen(3000);
node.js app (app.js) code continues with:
io.of('/nodejs').on('connection', function(socket) { //optional settings: io.set('heartbeat timeout', 3000); io.set('heartbeat interval', 1000); //listener for when a user is added socket.on('add user', function(data) { socket.join('AnyRoomName'); socket.broadcast.emit('user joined', data); }); //listener for when a user leaves socket.on('remove user', function(data) { socket.leave('AnyRoomName'); socket.broadcast.emit('user left', data); }); //sample listener for any other function socket.on('named-event', function(data) { //code.... socket.broadcast.emit('named-event-broadcast', data); }); // add more listeners as needed... use different named-events... });
finally, on the client side (created as nodejs.js):
//notice the /nodejs path var socket = io.connect('https://www.example.com/nodejs'); //listener for user joined socket.on('user joined', function(data) { // code... data shows who joined... }); //listener for user left socket.on('user left', function(data) { // code... data shows who left... }); // sample listener for any function: socket.on('named-event-broadcast', function(data) { // this receives the broadcast data (I use json then parse and execute code) console.log('data1=' + data.data1); console.log('data2=' + data.data2); }); // sample send broadcast json data for user joined: socket.emit('user joined', { 'userid': 'userid-value', 'username':'username-value' }); // sample send broadcast json data for user left //(I added the following with an event listener for 'beforeunload'): // socket.emit('user joined', { // 'userid': 'userid-value', // 'username':'username-value' // }); // sample send broadcast json data for any named-event: socket.emit('named-event', { 'data1': 'value1', 'data2':'value2' });
In this example when the JS loads, it will emit to the socket a "named-event" sending the data in JSON to the node.js/socket.io server.
Using the io and socket on the server under path /nodejs (connected by client), receives the data an then resends it as a broadcast. Any other users in the socket would receive the data with their listener "named-event-broadcast". Note that the sender does not receive their own broadcast.