WebSocketもHerokuも話題になった当時、それぞれちょっと試しただけでしたが、モバイル環境でリアルタイム通信するときにとても強力な組み合わせであることを最近改めて感じます。
WebSocketは、ローカルでテストサーバ(nodejs)立てても、何も広がりがないのですが、SSL対応でインターネット上のサーバ(Ruby)が使えるHerokuとなると、用途が一気に広がります。すでにやっておられる方も多いと思いますが、私もHerokuのWebSocketアプリを試してみました。
環境: Ubuntu 15.10
apt-get install ruby
apt-get install ruby-dev
apt-get install openssl
apt-get install libssl-dev
apt-get install bundler
参考: https://devcenter.heroku.com/articles/getting-started-with-ruby#set-up
wget -O- https://toolbelt.heroku.com/install-ubuntu.sh | sh
heroku login (登録アカウントのメールアドレス、パスワードを入力)
参考: https://devcenter.heroku.com/articles/ruby-websockets
git clone https://github.com/heroku-examples/ruby-websockets-chat-demo.git
cd ruby-websockets-chat-demo
vi Gemfile (「ruby “2.1.5”」に 変更)
vi middlewares/chat_backend.rb (Redisを使わないように変更)
sudo gem install puma -v ‘2.6.0’
bundle install –path vender/bundle
git commit -m “init”
heroku create
git push heroku master
ローカルでサーバを起動する場合、
git push heroku master
のかわりに、
bundle exec rackup
このとき、以下のクラスを追加する必要がありました。
参考: https://github.com/jeremyevans/roda/issues/44
1 2 3 4 5 |
class Rack::Lint::HijackWrapper def to_int @io.to_i end end |
Redisを使わないように変更したchat_backend.rb (参考サイトに説明あり)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
require 'faye/websocket' require 'thread' require 'redis' require 'json' require 'erb' module ChatDemo class ChatBackend KEEPALIVE_TIME = 15 # in seconds CHANNEL = "chat-demo" def initialize(app) @app = app @clients = [] end def call(env) if Faye::WebSocket.websocket?(env) ws = Faye::WebSocket.new(env, nil, {ping: KEEPALIVE_TIME }) ws.on :open do |event| p [:open, ws.object_id] @clients << ws end ws.on :message do |event| p [:message, event.data] @clients.each {|client| client.send(event.data) } end ws.on :close do |event| p [:close, ws.object_id, event.code, event.reason] @clients.delete(ws) ws = nil end ws.rack_response else @app.call(env) end end private def sanitize(message) json = JSON.parse(message) json.each {|key, value| json[key] = ERB::Util.html_escape(value) } JSON.generate(json) end end end |
Webブラウザの他に、コマンドラインから起動するWebSocketクライアントもテストしてみました。
参考: http://shokai.org/blog/archives/7223
sudo gem install websocket-client-simple
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
require 'rubygems' require 'websocket-client-simple' ws = WebSocket::Client::Simple.connect 'http://xxxxxxxx.herokuapp.com/' ws.on :message do |msg| puts msg.data end ws.on :open do ws.send '{"handle":"zzzzz", "text":"hello"}' end ws.on :close do |e| p e exit 1 end loop do ws.send STDIN.gets.strip end |
URLとws.sendで送るメッセージをHerokuサンプルに合わせるためJSON形式にしただけであとは参考サイトのままです。