Module: Sinatra::Streaming
Relationships & Source Files | |
Namespace Children | |
Modules:
| |
Defined in: | sinatra-contrib/lib/sinatra/streaming.rb |
Overview
::Sinatra
1.3 introduced the #stream helper. This addon improves the
streaming API by making the stream object imitate an IO object, turning
it into a real Deferrable and making the body play nicer with middleware
unaware of streaming.
IO-like behavior
This is useful when passing the stream object to a library expecting an IO or StringIO object.
get '/' do
stream do |out|
out.puts "Hello World!", "How are you?"
out.write "Written #out.pos
bytes so far!\n"
out.putc(65) unless out.closed?
out.flush
end
end
Better Middleware Handling
Blocks passed to #map! or #map will actually be applied when streaming takes place (as you might have suspected, #map! applies modifications to the current body, while #map creates a new one):
class StupidMiddleware def initialize(app) @app = app end
def call(env)
status, headers, body = @app.call(env)
body.map! { |e| e.upcase }
[status, headers, body]
end
end
use StupidMiddleware
get '/' do stream do |out| out.puts "still" sleep 1 out.puts "streaming" end end
Even works if #each is used to generate an Enumerator:
def call(env) status, headers, body = @app.call(env) body = body.each.map { |s| s.upcase } [status, headers, body] end
Note that both examples violate the ::Rack
specification.
Setup
In a classic application:
require "sinatra" require "sinatra/streaming"
In a modular application:
require "sinatra/base" require "sinatra/streaming"
class MyApp < Sinatra::Base helpers Sinatra::Streaming end
Instance Method Summary
Instance Method Details
#stream
[ GitHub ]# File 'sinatra-contrib/lib/sinatra/streaming.rb', line 79
def stream(*) stream = super stream.extend Stream stream.app = self env['async.close'].callback { stream.close } if env.key? 'async.close' stream end