構成
127.0.0.1:3000
で socket.io v2系 のサーバーが LISTEN していると仮定。
Apache 2.4.27
必要なモジュールは以下の通り。
- mod_proxy
- mod_rewrite
- mod_proxy_wstunnel
バックエンドへの通信は http://, ws:// で行い、TLSはリバースプロキシで落とす。
# ......
# 必ず VirtualHost の中に記述すること
<VirtualHost _default_:443>
# ......
# リライトを有効化
RewriteEngine on
# パスが /socket.io/ で始まり、クエリに transport=websocket が含まれているとき、
RewriteCond "%{REQUEST_URI}" "^/socket.io/" [NC]
RewriteCond "%{QUERY_STRING}" "transport=websocket" [NC]
# パスを保持したまま WebSocket プロトコルでローカルホストにプロキシを通す。
RewriteRule "/(.*)" "ws://127.0.0.1:3000/$1" [P,L]
# もちろんフォワードプロキシは無効化
ProxyRequests off
# それ以外のリクエストのうち /socket.io/ で始まるものは、localhost に通す。
ProxyPass "/socket.io/" "http://127.0.0.1:3000/socket.io/"
ProxyPassReverse "/socket.io/" "http://127.0.0.1:3000/socket.io/"
# ......
</VirtualHost>
# ......
補足
transport=websocket がクエリに含まれているとき、
socket.io は WebSocket へのプロトコルアップグレードを要求している。
従って、この時だけ WebSocket のプロトコルとして転送する。
それ以外のときは、フォールバックの可能性等もあるため http で転送。
Qiita にこれ以外の設定もあるが、フォールバックしか動いていない可能性が高いので要注意。
Nginx 1.13.3
詳細な情報は以下にあるため、そちらを参照すると良い。
https://www.nginx.com/blog/nginx-nodejs-websockets-socketio/
Apacheの場合と違って、ほとんど何も考えずに流してあげれば動いてくれる。
# Upstream の設定。
# 流したい先をここに記述する。
upstream websocket {
server localhost:3000;
}
# ......
server {
# ......
location /socket.io/ {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_pass http://websocket;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade; # どのプロトコルにアップグレードするかを残す
proxy_set_header Connection "upgrade"; # とりあえずプロトコルをアップグレードすることにする
}
# ......
}
動作確認法
Chrome の Developer Tools などを活用して確認できる。