※1 執筆時のRailsはバージョン5.0.0.1。
※2 Webサーバにはnginxを使用。
※3 リバースプロキシにnginxを使った構成も対応する。
Rails5.0.0.1はすでにインストールされているものとする。
定番のコマンドでプロジェクトを作る。
$ rails new sample-project
次にチャンネルを作る。
これにより作成されるファイルは下記の通り。
<hoge_channel.rb>はサーバサイドが行う処理が記述される。
<hoge.coffee>はクライアントサイドが行う処理が記述される。
$ rails g channel hoge piyo (hogeがチャンネル名、piyoはアクション名) create app/channels/hoge_channel.rb identical app/assets/javascripts/cable.js create app/assets/javascripts/channels/hoge.coffee
※ もしエラーが出たらGemfileのtherubyracerがコメントアウトされていると思うので有効にしてbundle installする。
<development.rb, production.rb>に「ソケットを許可するアクセス元」を追記。
つまり自分のドメインを書けば良い。
config.action_cable.allowed_request_origins = ['http://hogepiyo.com']
Railsの準備は以上。
次はnginxサーバの設定に移る。
!注意点!
rc版のRailsでは<route.rb>に
mount ActionCable.server => '/cable'
を書いたり、
<cable.coffee>の
@App ||= {} App.cable = ActionCable.createConsumer()
をコメント外したりという作業が必要だった。
Ruby on Rails 5.0.0.1ではこれら作業は必要ない。
ここからNginxの設定。
RailsではWebSocketを使うのにPuma等が推奨されている。
Unicornはあいにく非推奨、これはシングルスレッドノンブロッキングI/Oという仕様のため。
そのためPumaに対してPIDないしSocketでアクセスを流してあげるのが好ましい(たぶん)
設定内容は単純に/cable(RailsのWebSocketの標準設定)へのアクセスをupgradeしてPumaに渡すだけである。
Nginxのconfファイルの参考
upstream puma { server unix:/var/run/puma.sock fail_timeout=0; } server { 中略 location /cable { proxy_pass http://puma/cable; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } 中略 }
これで晴れてActionCable(WebSocket)機能が動くようになる。
また、nginxのリバースプロキシがある場合は、リバースプロキシにも設定が必要になる。
アプリケーションサーバと同様に/cableに対して
upgradeしてアプリケーションサーバへアクセスを流すだけである。
server { 中略 location /cable { proxy_pass http://backend; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; } 中略 }
もしこの記述をしなかった場合サーバは404を返すうえに、
アプリケーションサーバではこのようなエラーログが残る。
ブラウザのコンソールに表示されるログ WebSocket connection to 'ws://hogepiyo.com/cable' failed: Error during WebSocket handshake: Unexpected response code: 404 Railsのログにはこのように出力される Started GET "/cable" for *.*.*.* at YYYY-MM-DD 00:00:00 +0900 Started GET "/cable/"[non-WebSocket] for *.*.*.* at YYYY-MM-DD 00:00:00 +0900 Failed to upgrade to WebSocket (REQUEST_METHOD: GET, HTTP_CONNECTION: close, HTTP_UPGRADE: ) Finished "/cable/"[non-WebSocket] for *.*.*.* at YYYY-MM-DD 00:00:00 +0900 ※ IP等は伏せてる
ここで注意しないといけないのがこの一行を忘れないこと。
> proxy_set_header Host $host;