Sinatraとsinatra-contribのStreamingの違い
Sinatra標準のStreamingと、公式拡張sinatra-contribのStreamingの違いについてメモ。
Sinatra標準Streaming
使い方
# coding: utf-8 require "sinatra" get '/' do stream do |out| out << "やあ<br>" sleep 1 out << "こんにちは、<br>" sleep 1 error_message = "お前はここで終わりだがな!" out.callback { p error_message } #=> closeされたときに実行される out << "世界" end end
WEBrickだと対応してないので、thinで。
$ ruby classic_streaming.rb -s thin
まあデフォルトだと「<<」と「callback」しかできることはない。
他にはstreamに渡すときに第1引数をtrueにすると、そのコネクションが開きっぱなしになるらしい。
以下、超簡単なpub/sub実装。
require "sinatra" connections = [] # subscribe側 get '/' do # trueならなんでもいい、そう、シンボルでもね。 stream(:keep_open) do |out| connections << out end end # publish側 get '/send' do connections.each do |out| out << params[:message]+"<br>" end "send message: #{params[:message]}" end
いいね!
おわり。
sinatra-contribのStreaming
これをもう少し拡張したのがsinatra-contribのStreamingで別途インストールが必要になる。
# Gemfile gem "sinatra-contrib"
とはいえ、唯一の特徴がIOインスタンスっぽく扱える、というだけのようだ。
classicスタイルでの使い方
require "sinatra" require "sinatra/streaming" get "/" do stream do |out| out.write "妖怪が鍛えた<br>" sleep 1 out.syswrite "この楼観剣に<br>" sleep 1 out.write_nonblock "斬れぬものなど<br>" sleep 1 out.puts "あんまり無い" out.putc(33) out.putc(33) out.printf("<%s>", "br") sleep 1 out.print "#{out.pos} bytes" end end
なんか公式の例で
out.flush
とできるようになっているけど、中身の実装はなかった。。。(華麗にスルー)
まあ特別IOっぽくしたいっていうことでも無い限り、標準の方で事足りると思う。
ちなみ
また、uu59のメモ | Sinatra 1.3で追加されたstreamのHTTP解剖学 の通り
ちょいちょい送信することを示す「Transfer-Encoding: chunked」がない(わざと実装していない?)みたいなので
あんまりきっちりしたことには使えないとも思う。
$ curl -i localhost:4567/ HTTP/1.1 200 OK Content-Type: text/html;charset=utf-8 X-XSS-Protection: 1; mode=block X-Content-Type-Options: nosniff X-Frame-Options: SAMEORIGIN Connection: close Server: thin 1.5.1 codename Straight Razor
公式ドキュメント
Sinatra::Streaming (part of Sinatra::Contrib)
参考
uu59のメモ | Sinatra 1.3で追加されたstreamのHTTP解剖学
ありがとうございます。