WebSocket handshake: Unexpected response code: 400
Ostatnio wdrażałem REST api wykorzystujące websockety, postawione na node.js, dokładniej na frameworku feathers.js. Na hostingu jest zainstalowany Apache/2.4.18. Dostęp do api poprzez reverse proxy.
VirtualHost jaki napisałem wygląda mniej więcej tak:
<VirtualHost *:80>
ServerAdmin admin@example.com
ServerName node.server.domain.name
ServerAlias www.node.server.domain.name
ProxyPreserveHost On
ProxyPass / http://127.0.0.1:port/
ProxyPassReverse / http://127.0.0.1:port/
</VirtualHost>
Wszystko z grubsza wyglądało, że działa. W czasie rzeczywistym strona klienta się aktualizowała. Jednak w zakładce console chrome devetools pojawiał się niepokojący, czerwony error 😉
WebSocket connection to ‚ws://node.server.domain.name/socket.io/?EIO=3&transport=websocket&sid=OT8njO2Hava50PIsAACU’ failed: Error during WebSocket handshake: Unexpected response code: 400
Hmm, coś chyba nie tak. Dodatkowo w zakładce network/xhr piękna, niekończąca się lista wywołań. Czyli websockety nie działają, a realtime jest uzyskiwany poprzez ajaxowy long polling.

Rozwiązaniem okazało się doinstalowanie proxy_wstunnel. Czyli:
sudo a2enmod proxy_wstunnel
oraz aktualizacja VirtualHost’a api do postaci:
<VirtualHost *:80>
ServerAdmin admin@example.com
ServerName node.server.domain.name
ServerAlias www.node.server.domain.name
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/socket.io [NC]
RewriteCond %{QUERY_STRING} transport=websocket [NC]
RewriteRule /(.*) ws://localhost:port/$1 [P,L]
ProxyPreserveHost On
ProxyPass / http://127.0.0.1:port/
ProxyPassReverse / http://127.0.0.1:port/
</VirtualHost>