websocket-railsを使ってRailsでWebSocketによるPush通知を実装する話をします。
websocket-railsを使って簡単なデモを作ってHerokuにアップしました。Twitter Streaming APIで受け取ったデータをWebSocketでリアルタイムにクライアントへ送るものです。ソースコードもgithubにありますので参考にどうぞ。
セットアップ
gem "websocket-rails"
$ bundle
$ rails g websocket_rails:install
最後のコマンドで設定ファイルを追加し、application.js
をクライアント側のライブラリをrequire
するように変更します。
開発環境ではRack::Lockを無効にしないとエラーになるので以下のようにしておきます。
TwitterStreamingSample::Application.configure do
config.middleware.delete Rack::Lock
end
実装
WebSocket接続したクライアントに対して任意のタイミングでメッセージを送りたい場合、channelというものを使うと簡単に実装できます。
def create
# ...
WebsocketRails[:streaming].trigger "create", tweet
head :ok
end
これで、"streaming"というチャネルに"create"というメッセージをtweetのデータとともに送信します。WebSocketRails
という定数はどこからでもアクセス可能なので、任意のタイミングでチャネルにメッセージを送ることが可能です。
dispatcher = new WebSocketRails("ws://#{localhost.host}/websocket")
channel = dispatcher.subscribe("streaming")
channel.bind "create", (tweet) ->
# something
次にクライアント側では、まずWebSocket接続を行います。WebSocket接続はwebsocket-railsが追加する/websocket
というパスに対してリクエストを送ります。
接続が成功するとdispatcherと呼ばれるオブジェクトを返します。このオブジェクトはWebSocketサーバーとやり取りをする中心的なオブジェクトです。dispatcher#subscribe(チャネル名)
で特定のチャネルを購読するオブジェクトを取得できるので、あとはメッセージを受け取ったときのコールバックを設定するだけです。
これだけ
これだけでdispatcherでsubscribeしたクライアントすべてに対してRailsからPush通知ができます。
nginx
本番環境でnginxとともに運用する場合、nginx側の設定も必要です。nginxでWebSocketのプロキシを行うには1.3.13以降であることが必要です。
location /websocket {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
"Upgrade"というヘッダーはプロトコルをHTTPからWebSocketに変更するために必要な情報で、RFCで定められています。
Heroku
最近、HerokuがWebSocketのサポートを開始しました。ただし、まだβ版での開始なので、デフォルトのままではWebSocketを利用できません。以下のコマンドを実行するとWebSocketの機能がオンになります。
$ heroku labs:enable websockets