Configuration d'Apache 2.4 mod_proxy_wstunnel pour Socket.IO 1.0

15

J'essaye de configurer Apache 2.4 pour mandater la connexion websocket pour socket.io à un serveur websocket node.js, en utilisant mod_proxy_wstunnel. Nous avons bien fonctionné avec socket.io 0.9, mais avec la version 1.0, ils ont changé le point de terminaison du socket en paramètre de requête, et maintenant j'ai du mal à configurer apache avec les instructions de proxy correctes.

Toutes les demandes à /socket.io/?EIO=N&transport=websocket(où N est un chiffre, généralement 2) doivent être transmises à ws://localhost:8082/socket.io/, mais toutes les autres demandes doivent être transmises à http://localhost:8082/socket.io/.

J'ai essayé des variantes des deux configurations suivantes:

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/

D'après mes recherches sur Google, ProxyPass et les emplacements ne peuvent pas cibler les chaînes de requête, y a-t-il une autre option ici? Les chemins sont codés en dur dans socket.io, donc à court de bifurquer la bibliothèque entière, je ne peux pas les changer.

ChiperSoft
la source

Réponses:

39

Utilisez les conditions de réécriture pour correspondre à ce cas particulier:

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

REMARQUE Comme Mark W l'a noté ci-dessous. Ceux-ci doivent être saisis au niveau vhost et non au niveau serveur ou .htaccess.

Vous pouvez également référencer un équilibreur:

<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
PeterPramb
la source
+100000 Tu as fait ma journée. Ça fait des heures. J'ai utilisé le premier extrait de code. Je n'ai pas besoin d'équilibreur pour le moment.
Eamorr
Je n'arrive pas à faire fonctionner ça. Apache continue de répondre avec un code 404. Il apparaît dans le journal d'accès comme s'il essayait de charger un fichier normal, et le processus de nœud de socket ne montre aucun signe de réception de la demande (il montre l'appel du fichier socket.io.js)
ChiperSoft
1
Il semble que mod_rewrite ne connaisse pas le protocole ws: //. Je vois cela dans mon journal de réécriture: forcing proxy-throughput with http://[REDACTED].dev/ws://localhost:8082/socket.io/(domain.dev
ChiperSoft
C'est probablement pourquoi: issues.apache.org/bugzilla/show_bug.cgi?id=55598 Il semble que la prise en charge du protocole ait été ajoutée dans Apache 2.5
ChiperSoft
5
REMARQUE : ces blocs doivent être placés dans le <VirtualHost>bloc dans l'ordre exact décrit, même si vous utilisez la racine du document (par exemple /var/www/html). J'ai passé près de 2 heures à essayer de comprendre pourquoi ces changements ne fonctionnaient pas correctement, seulement pour découvrir que les RewriteRulene fonctionnaient pas au niveau racine httpd.conf(bien que ProxyPassfonctionnaient). Les ProxyPassdirectives ne fonctionnent pas dans des <Directory>blocs ou des .htaccessfichiers (bien que ce soit le RewriteRulecas), donc l'endroit logique pour regrouper ces modifications est <VirtualHost>.
Mark W