This add's to @Andrew Moss' answer as to how to correctly configure the VirtualHost
to work with socket.io 1.0! Feel free to skip the part about CentOS!
If you're stuck on CentOS 6, here is how to do it:
- Download the backported source for the
mod_proxy_wstunnel
module here (either clone the Gist or download the files individually)
- Install everything necessary to build:
yum install make gcc httpd-devel
- Setup an RPM Build environment (basically an unprivileged user and some directories)
- Copy the
.c
-file into the SOURCES
subfolder of the environment and the .spec
-file into the SPECS
subfolder.
- Run
rpmbuild -ba mod_proxy_wstunnel.spec
- The package is now in the
SRPMS
subfolder
- Install the package:
rpm -i /path/to/package.rpm
- Profit
This will also automatically load the module in Apache, so you just have to restart it with service httpd restart
.
Setting up a VirtualHost
to actually serve the Socket.io server and client-script (which is by default available under http://your.server/socket.io/socket.io.js
) is a bit more complicated on Apache 2.2, because of a Bug in the mod_proxy
module:
Given the following rewrite rule:
RewriteRule ^/ws(.*)$ ws://localhost:9000/ws [P]
mod_rewrite
treats this a filepath so the access log shows:
[26/Sep/2013:09:46:07 -0400] "GET /ws://localhost:9000/ws HTTP/1.1" 400 317
So, you can't use the ws
-protocol in a rewrite-rule, because that will internally turn into an HTTP GET request.
There is a workaround though:
<VirtualHost *:80>
ServerName your.server
# Proxy socket.io Websocket
RewriteEngine On
# socket.io 1.0+ starts all connections with an HTTP polling request
RewriteCond %{QUERY_STRING} transport=polling [NC]
RewriteRule /(.*) http://localhost:8081/$1 [P]
ProxyRequests Off
# Explicitly send the request for the client-script to HTTP:
ProxyPass /socket.io/socket.io.js http://localhost:8081/socket.io/socket.io.js
ProxyPassReverse /socket.io/socket.io.js http://localhost:8081/socket.io/socket.io.js
# Anything else goes to the WebSocket protocol:
ProxyPass /socket.io/ ws://localhost:8081/socket.io/
ProxyPassReverse /socket.io/ ws://localhost:8081/socket.io/
# Any additional stuff (the actual site) comes here
ProxyPass / http://localhost:8081/
ProxyPassReverse / http://localhost:8081/
</VirtualHost>
This makes sure that everything sent to /socket.io
goes to the ws://
-protocol, except the request for long-polling (which is a fallback mechanism when WebSockets are not available) and the request for the client-library.