How to make Socket IO work over HTTPS using node.js

Viewed 6092

This is frustrating me like crazy!

i'm using a proxy so that any requests that go to myurl/APP/ are answered by node.js at myurl:8001

I now need this to work over https. easy.... i thought.

i have Apache serving up the old version from the public folder. That is stand alone, and when i'm done building this, it will just be removed. but for now needs to remain in tact and accessible. Lets encrypt is setup on this. and https://myurl works fine, showing content from the public folder of course.

if i go to https://myurl:8001 then chrome says "site can't be reached". If i go to http://myurl:8001 it works fine. I think this is because https default port is 443. I have VPS not dedicated so i don't think i can alter that. And surely if i did alter the ssl port then it wont work for the public folder??

i'll show you the basics of whats going on;

app.js;

   var express = require('express');
var app = express();
var serv = require('http').Server(app);

app.get('/',function(req, res) {
    res.sendFile(__dirname + '/client/index.html');
});
app.use('/client',express.static(__dirname + '/client'));

serv.listen(8001);
console.log("Server started.");

var SOCKET_LIST = {};

var io = require('socket.io')(serv,{});
io.sockets.on('connection', function(socket){
    socket.id = Math.random();
    socket.x = 0;
    socket.y = 0;
    socket.number = "" + Math.floor(10 * Math.random());
    SOCKET_LIST[socket.id] = socket;

    socket.on('disconnect',function(){
        delete SOCKET_LIST[socket.id];
    });

});

setInterval(function(){
    var pack = [];
    for(var i in SOCKET_LIST){
        var socket = SOCKET_LIST[i];
        socket.x++;
        socket.y++;
        pack.push({
            x:socket.x,
            y:socket.y,
            number:socket.number
        });    
    }
    for(var i in SOCKET_LIST){
        var socket = SOCKET_LIST[i];
        socket.emit('newPositions',pack);
    }




},1000/25);

client/index.html;

<canvas id="ctx" width="500" height="500" style="border:1px solid #000000;"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.3/socket.io.js"></script>

<script>
    var ctx = document.getElementById("ctx").getContext("2d");
    ctx.font = '30px Arial';

    var socket = io.connect('http://www.myurl:8001', {path: "/socket.io"});

    socket.on('newPositions',function(data){
        ctx.clearRect(0,0,500,500);
        for(var i = 0 ; i < data.length; i++)
            ctx.fillText(data[i].number,data[i].x,data[i].y);      
    });
</script>

It works fine as the code is but only over http. I need this to work over SSL

i need this line to work when its https;

var socket = io.connect('https://www.myurl:8001', {path: "/socket.io"});

How is this possible?

any help is greatly appreciated.

2 Answers

Your server code is only creating an http server, not an https server and since socket.io uses your http server, it will only run on http. http and https servers are different (the https server implements certificate verification and data encryption which is not present with the http server).

To make an https server, change this:

var express = require('express');
var app = express();
var serv = require('http').Server(app);

to this:

const express = require('express');
const app = express();
const options = {...};    // fill in relevant certificate info here
const serv = require('https').createServer(options, app);

And, you will have to fill in the appropriate certificateinfo in the options data structure.

https.createServer() code examples are here.

You can then run your https server on any port you want as long as you connect to it with an https URL and the right port number. You are correct that the default port for an https URL is 443 so if not port number is specified, that's what a browser will attempt to use.

Related