This extension is part of the Sinatra::Contrib project. Run gem install sinatra-contrib to have it available.
Sinatra::Streaming¶ ↑
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