Gorilla Web Sockets live does not work

I cut and pasted a sample code from here This code works out of the box on my local computer.

But when moving to a VPS with Nginx proxy this fails. As this “converts” from https:// to wss:// I have no clue what I have done wrong. https://ws.go4webdev.org (live)

image

The console gives this error:

WebSocket connection to ‘wss://localhost:8080/echo’ failed:

And the page shows up like this:

image

I suspect that it is this line that is the problem, but I cannot figure out the syntax.

//var addr = flag.String("addr", "127.0.0.1:8080", "http service address") <-- works on my local computer

var addr = flag.String("addr", "https://ws.go4webdev.org", "http service address") <-- fails on VPS

My gut feeling tells me that this is close to a CORS error, but I cannot confirm.

Any clue how I can make this work?

The answer lies in your template:

homeTemplate.Execute(w, "ws://"+r.Host+"/echo")

Are you running this behind a reverse proxy or something? A simple fix would be to get rid of that part of the template and instead push the logic to the browser. Something like this:

ws = new WebSocket("ws://" + document.location.host + "/echo");

Thanks, but when move this to the javascript there is no value assigned to the ws. I have updated the javascript and added some alerts and here it is live (still not working).

It seems to me that the page is loaded twice and maybe clear the value of ws?

window.addEventListener("load", function(evt) {
  alert("value of ws at load " + ws)
  var output = document.getElementById("output");
  var input = document.getElementById("input");
  var ws;
  var print = function(message) {
    var d = document.createElement("div");
    d.textContent = message;
    output.appendChild(d);
    output.scroll(0, output.scrollHeight);
  };

  document.getElementById("open").onclick = function(evt) {
    alert("value at ws at open: " + ws)

    if (typeof ws !== 'undefined' && ws !== null) {
      return
    }
    
    alert("assign value to ws")
    ws = new WebSocket("ws://" + document.location.host + "/echo");
    alert("ws://" + document.location.host + "/echo") // this is not executed for some reason...
    alert(ws);

    ws.onopen = function(evt) {
      print("OPEN");
    }
    ws.onclose = function(evt) {
      print("CLOSE");
      ws = null;
    }
    ws.onmessage = function(evt) {
      print("RESPONSE: " + evt.data);
    }
    ws.onerror = function(evt) {
      print("ERROR: " + evt.data);
    }
    return false;
  };
  document.getElementById("send").onclick = function(evt) {
    if (!ws) {
      return false;
    }
    print("SEND: " + input.value);
    ws.send(input.value);
    return false;
  };
  document.getElementById("close").onclick = function(evt) {
    if (!ws) {
      return false;
    }
    ws.close();
    return false;
  };
});

Maybe you need wss. I had a WebSocket project once and when deployed behind a reverse proxy (nginx), it was accessed through wss. Here are a couple of code snippets:

// The websocket URL scheme. 
var wsScheme="{{.WSScheme}}";
...
  wsConn =  new WebSocket(wsScheme+"//" + wsUrl +"/socket");
	w.Header().Set("Content-Type", "text/html")

	t,err := template.ParseFiles("test.html")
	if err != nil {
		http.Error(w, fmt.Sprintf("parse file error: %s", err), http.StatusInternalServerError)
		return
	}

	var scheme struct {
		WSScheme string
	}
	if (!s.RunningLocal) {
		scheme.WSScheme="wss:"
	} else {
		scheme.WSScheme="ws:"
	}

	err = t.Execute(w, scheme)
	if err != nil {
		http.Error(w, fmt.Sprintf("template error: %s", err), http.StatusInternalServerError)
		return
	}

I’m wondering if, since you have those buttons inside a form, they are attempting to submit the form when you press them. Try changing those buttons to button type="button" so they don’t submit the form, causing a reload.

Thank you! I did this and got ONE step further :slight_smile:

Now at least the console shows one error:

ws.js:21 WebSocket connection to ‘wss://ws.go4webdev.org/echo’ failed: Error during WebSocket handshake: Unexpected response code: 400

Any clue how I track down this?

Yes, I needed the wss.

I think I found one solution. It seems that Websockets is an old protocol that is only supported by HTTP 1.1 (cannot confirm this). But when added this to the Nginx sites-available, it seems to work.

    location / {
        proxy_pass http://localhost:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
    }

If anybody can confirm this, I should be nice to know.