Search code examples
apachesocketswebsocketmod-proxyphpwebsocket

WebSockets (Apache ProxyPass)


I'm looking to setup a simple WebSocket connection through Apache.

I'm running two web servers one being Apache and the other a simple PHP WebSocket server to handle socket connections, this is running on a Ubuntu box hosted on RackSpace.

I've done a lot of research already and still haven't found a good example that shows basic configuration to setup a WebSocket server in any language (in this case PHP) on a remote host, every example I've seen has been using 'localhost' which in my opinion is quite useless.


So Apache's root is /var/www/html (default) and is listening on port 8080, so for example purpose (www.mydomain.com:8080) below is the source code for the index.html page.

<html>
<head>
<script>
document.addEventListener("DOMContentLoaded", init);
function init(){
    var socket = new WebSocket("ws://www.mydomain.com:8080/sockets");
    setInterval(timer.sockstate, 3000, socket);
    socket.addEventListener('open', sock.open);
    socket.addEventListener('message', sock.msg);
    socket.addEventListener('error', sock.err);
    socket.addEventListener('close', sock.close);
} 
var timer = {
    "sockstate": function(o){
        switch(o.readyState){
            case 0:
                console.log('CONNECTING...');
                break;
            case 1:
                console.log('OPEN...');
                break;
            case 2:
                console.log('CLOSING...');
                break;
            case 3:
                console.log('CLOSED...');
                break;
        }
    }
};
var sock = {
    "open": function(e){
        console.log(e);
    },
    "msg": function(e){
        console.log(e);
    },
    "err": function(e){
        console.log(e);
    },
    "close": function(e){
        console.log(e);
    }
};
</script>
</head>
<body></body>
</html>

Now the PHP server is listening to 127.0.0.1 on port 9000 here is the source code for it, and it's starts up fine via cmd line php -q /var/www/html/sockets/server.php


Finally my configuration file in Apache

<VirtualHost *:8080>
    ServerName www.mydomain.com
    DocumentRoot /var/www/html  

    ProxyPass "/sockets/" "http://127.0.0.1:9000/"
    ProxyPassReverse "/sockets/" "http://127.0.0.1:9000/"
</VirtualHost>

I'm positive it's not a networking problem I ufw status to assure that both ports (8080/9000) are allowed, and made sure mod_proxy and mod_proxy_wstunnel are being loaded.

Question: So what am I doing wrong here in my Apache Config?


Solution

  • I've just finished this setup on my own server, so I hope this helps someone. My config is very similar to yours. This is what I would change

    Javascript

    //Notice the path ends with a trailing hash. Don't know whether it matters
    var socket = new WebSocket('ws://www.domain.com:8080/socket/');
    

    VirtualHost

    # Protocol should be 'ws', not 'http', for mod_proxy_wstunnel to work
    ProxyPass "/sockets/" "ws://127.0.0.1:9000/"
    ProxyPassReverse "/sockets/" "ws://127.0.0.1:9000/"
    

    Because Apache forwards WS traffic, the websocket server does not need to be exposed to the public. You can keep port 9000 closed to the internet.

    I also have mod_proxy_http enabled, but I don't know whether it's required.

    If redirection is not happening, look at your Apache error log. You've already mentioned a couple of these things but make sure:

    • that mod_proxy and mod_proxy_wstunnel are loaded
    • that you restart Apache after changing modules or VirtualHost config
    • that the WS server is running and listening on port 9000
    • that the ProxyPass is in the correct VirtualHost