13

I'm trying to configure Apache 2.4 for proxying the websocket connection for socket.io to a node.js websocket server, using mod_proxy_wstunnel. We had this working fine with socket.io 0.9, but with the 1.0 release they changed the socket endpoint to a query parameter, and now I'm having trouble configuring apache with the correct proxy instructions.

All requests to /socket.io/?EIO=N&transport=websocket (where N is any digit, usually 2) need to be forwarded to ws://localhost:8082/socket.io/, but all other requests need to be forwarded to http://localhost:8082/socket.io/.

I've tried variations of both of the following configs:

ProxyPass /socket.io/?EIO=2&transport=websocket http://localhost:8082/socket.io/?EIO=2&transport=websocket
ProxyPassReverse /socket.io/?EIO=2&transport=websocket http://localhost:8082/socket.io/?EIO=2&transport=websocket

ProxyPass /socket.io/ http://localhost:8082/socket.io/
ProxyPassReverse /socket.io/ http://localhost:8082/socket.io/

.

RewriteRule /socket.io/?EIO=([0-9]+)&transport=websocket ws://localhost:8082/socket.io/ [QSA,P]

ProxyPass /socket.io/ http://localhost:8082/socket.io/
ProxyPassReverse /socket.io/ http://localhost:8082/socket.io/

I've gathered from my googling that ProxyPass and Locations can't target query strings, so is there any other option here? The paths are hard-coded into socket.io, so short of forking the entire library I can't change them.

37

Use Rewrite conditions to match for this special case:

RewriteEngine On
RewriteCond %{REQUEST_URI}  ^/socket.io            [NC]
RewriteCond %{QUERY_STRING} transport=websocket    [NC]
RewriteRule /(.*)           ws://localhost:8082/$1 [P,L]

ProxyPass        /socket.io http://localhost:8082/socket.io
ProxyPassReverse /socket.io http://localhost:8082/socket.io

NOTE As Mark W noted below. These must be entered at vhost level and not at server or .htaccess level.

You can also reference a balancer:

<Proxy balancer://http-localhost/>
    BalancerMember http://localhost:8082 keepalive=On smax=1 connectiontimeout=10 retry=600 timeout=900 ttl=900
    BalancerMember http://localhost:8083 keepalive=On smax=1 connectiontimeout=10 retry=600 timeout=900 ttl=900
    ProxySet lbmethod=bytraffic
</Proxy>

<Proxy balancer://ws-localhost/>
    BalancerMember ws://localhost:8082 keepalive=On smax=1 connectiontimeout=10 retry=600 timeout=900 ttl=900
    BalancerMember ws://localhost:8083 keepalive=On smax=1 connectiontimeout=10 retry=600 timeout=900 ttl=900
    ProxySet lbmethod=bytraffic
</Proxy>

RewriteEngine On
RewriteCond %{REQUEST_URI}  ^/socket.io                [NC]
RewriteCond %{QUERY_STRING} transport=websocket        [NC]
RewriteRule /(.*)           balancer://ws-localhost/$1 [P,L]

ProxyPass        /socket.io balancer://http-localhost/socket.io
ProxyPassReverse /socket.io balancer://http-localhost/socket.io
  • +100000 You made my day. Been at this for hours. I used the first code snippet. I don't need a balancer at the moment. – Eamorr Sep 7 '14 at 15:30
  • I'm not able to get this to work. Apache keeps responding with a 404 code. It shows up in the access log as if it's trying to load a normal file, and the socket node process shows no sign of receiving the request (it does show the call for the socket.io.js file) – ChiperSoft Sep 22 '14 at 21:54
  • 1
    It appears that mod_rewrite doesn't know the ws:// protocol. I see this in my rewrite log: forcing proxy-throughput with http://[REDACTED].dev/ws://localhost:8082/socket.io/ (domain.dev – ChiperSoft Sep 22 '14 at 22:33
  • This is probably why: issues.apache.org/bugzilla/show_bug.cgi?id=55598 Looks like support for the protocol was added in Apache 2.5 – ChiperSoft Sep 22 '14 at 22:35
  • 5
    NOTE: These blocks should be placed within the <VirtualHost> block in the exact order described, even if you are using the document root (e.g. /var/www/html). I spent nearly 2 hours trying to figure out why these changes were not working properly, only to find out that the RewriteRule's were not functioning at the root level of httpd.conf (although ProxyPass was working). The ProxyPass directives do not work in <Directory> blocks or .htaccess files (although the RewriteRule's do), so the logical place to group these changes is in <VirtualHost>. – Mark W Sep 9 '15 at 18:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.