Search code examples
javascriptdockernginxwebsocketnode-red

websockets with javascript and nginx on docker


i have a docker compose that contains 3 containers " node-red , influxdb , a html with JavaScript webpage with nginx:alpine image " in the html and JavaScript webpage i have a list of images and i change the image according to the data that come from node red via websockets

enter image description here

and i receive my data with this JavaScript function

function startConnect() {
    document.getElementById('dt').click();
    socket = new WebSocket("ws://mywebsite.com:1880/ws/test");
    socket.onmessage = function(e) {onMessageArrived(e.data)}
    console.log("connected");
    socket.onopen = function() {socket.send("1")};
    
}

// Called when a message arrives
function onMessageArrived(message) {
    console.log("onMessageArrived: " + message);
    
    var obj = JSON.parse(message);
    
    document.getElementById("image1").src = "myimage/" + obj.L + "_DL.png";
    document.getElementById("image2").src = "myimage/" + obj.M + obj.F + obj.S + "_" + obj.Z48_70 + "_M.png";
    document.getElementById("image3").src = "myimage"+ obj.V + obj.V + "_X";
}

every thing worked fine until i have decided to use docker for "node-red and influx and the html webpage" and use nginxwithout docker with letsencrypt certifacts to handle the reverse proxy of my 3 containers.

The problem that i am facing is that i cannot receive data with websockets even though i change the socket = new WebSocket("ws://mywebsite.com:1880/ws/test") to socket = new WebSocket("ws://mywebsite.com:6100/ws/test") the port 6100 used by my webpage contain with this i am having an https error and with socket = new WebSocket("ws://192.170.0.6:6100/ws/test") the IP address of my webpage container and also with new WebSocket("ws://mywebsite/webpage/ws/test") this is handeled by nginx to route it the IP and the port used by my webpage container


Solution

  • If you are connecting to a WebSocket address that is being boot strapped via HTTPS then you need to use the wss: scheme rather than ws:

    So if you have enabled https on port 6100 then you need to use wss://mywebsite.com:6100/ws/test

    (also if you are using nginx as a reverse proxy is there any reason not to use the default ports of 80 and 443 for http/https respectively?)

    EDIT: If your proxy is presenting the default ports of 80/443 for http/https respectively then you should be using something like the following:

    function startConnect() {
        document.getElementById('dt').click();
        if (location.scheme === 'http:' ) {
          socket = new WebSocket("ws://mywebsite.com/ws/test");
        } else {
          socket = new WebSocket("wss://mywebsite.com/ws/test");
        }
        socket.onmessage = function(e) {onMessageArrived(e.data)}
        console.log("connected");
        socket.onopen = function() {socket.send("1")};
        
    }
    

    This will pick ws:// or wss:// depending on how the page is loaded (http vs https)