Module Sinatra::Streaming
In: lib/sinatra/streaming.rb

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

Methods

stream  

Classes and Modules

Module Sinatra::Streaming::Stream

Public Instance methods

[Validate]