Lighttpd with webSocket

Viewed 2660

I am trying to make a simple webapp which uses websocket for communication with the lighttpd server. Unfortunately my setup does not work and i do not know why. Search in the internet does not offer clear example how to use mod_wstunnel( May be someone has experience with lighttpd. Below you can find my sandbox:

lighttpd.conf

server.modules += ("mod_wstunnel", "mod_setenv")
server.indexfiles = ("index.html")
server.document-root = "/var/www/html/websocket"

$HTTP["url"] =~ "^/websockify" {
    wstunnel.server = ( "" => ( ( "host" => "127.0.0.1", "port" => "5900" ) ) )
    wstunnel.frame-type = "binary" 
    server.stream-request-body  = 2
    server.stream-response-body = 2
}

index.html

<h1>Real Time Messaging</h1>
<pre id="messages" style="height: 400px; overflow: scroll"></pre>
<input type="text" id="messageBox" placeholder="Type your message here" style="display: block; width: 100%; margin-bottom: 10px; padding: 10px;" />
<button id="send" title="Send Message!" style="width: 100%; height: 30px;">Send Message</button>

<script>
  (function() {
    const sendBtn = document.querySelector('#send');
    const messages = document.querySelector('#messages');
    const messageBox = document.querySelector('#messageBox');

    let ws;

    function showMessage(message) {
      messages.textContent += `\n\n${message}`;
      messages.scrollTop = messages.scrollHeight;
      messageBox.value = '';
    }

    function init() {
      if (ws) {
        ws.onerror = ws.onopen = ws.onclose = null;
        ws.close();
      }

      ws = new WebSocket("ws://127.0.0.1:5900/websockify")
      ws.onopen = () => {
        console.log('Connection opened!');
      }
      ws.onmessage = ({ data }) => showMessage(data);
      ws.onclose = function() {
        ws = null;
      }
    }

    sendBtn.onclick = function() {
      if (!ws) {
        showMessage("No WebSocket connection :(");
        return ;
      }

      ws.send(messageBox.value);
      showMessage(messageBox.value);
    }

    init();
  })();
</script>

Thanks in advance for the help.

2 Answers

lighttpd mod_wstunnel terminates the websocket tunnel in lighttpd, so that the client can, for example, send JSON over websockets to lighttpd, and lighttpd will decode and pass only the JSON to the backend.

If your server is its own websocket server and you want lighttpd to proxy the websocket connection to your websocket server, then see lighttpd mod_proxy or lighttpd mod_cgi and configure either of those modules to allow upgrade for Upgrade: websocket requests

I've been using the boost::beast c++ library to do something like this ... but the idea is the same for any other language/library.

Most of the available ws libraries (c++ or other) are thought as stand-alone websocket servers, designed to stand by themselves. To make them work as a lighttpd backend, the web server needs to proxy the websocket messages, making the libraries to believe they're receiving a direct client feed. Think of your server as communicating with lighttpd like a cgi app ... not exactly, but that's the idea.

Like gstrauss has said, lighttpd does this using mod_proxy:

server.modules   += ( "mod_proxy" )

$HTTP["url"] =~ "^/wsck" {
    proxy.server = ( "" => ( ( "host" => "127.0.0.1", "port" => "6000" ) ) )
    proxy.header = ( "upgrade" => "enable" )
}

From Boost::Beast pick a server example (other languages should have similar libraries):

https://www.boost.org/doc/libs/1_75_0/libs/beast/doc/html/beast/examples.html

Compile and leave it running in the background. Don't forget the ports between lighttpd.config and the websocket daemon must match!!!

From javascript the websocket is created by:

ws = new WebSocket("ws://yourServer.xyz/wsck");

All the other code can remain the same ... I haven't checked yours ;-)

Plase note that no port number is not used here. We are talking directly to lighttpd, which proxies the request to the backend running server (which has port 6000 open).

Hope it helps!

Related