Class: Rainbows::Sendfile

Inherits:
Struct
  • Object
show all
Defined in:
lib/rainbows/sendfile.rb

Overview

This middleware handles X-Sendfile headers generated by applications or middlewares down the stack. It should be placed at the top (outermost layer) of the middleware stack to avoid having its to_path method clobbered by another middleware.

This converts X-Sendfile responses to bodies which respond to the to_path method which allows certain concurrency models to serve efficiently using sendfile() or similar. With multithreaded models under Ruby 1.9, IO.copy_stream will be used.

This middleware is the opposite of Rack::Sendfile as it reverses the effect of Rack:::Sendfile. Unlike many Ruby web servers, some configurations of Rainbows! are capable of serving static files efficiently.

Compatibility (via IO.copy_stream in Ruby 1.9):

  • ThreadSpawn
  • ThreadPool
  • WriterThreadPool
  • WriterThreadSpawn

Compatibility (Ruby 1.8 and 1.9)

  • EventMachine
  • NeverBlock (using EventMachine)

DO NOT use this middleware if you're proxying to Rainbows! with a server that understands X-Sendfile (e.g. Apache, Lighttpd) natively.

This does NOT understand X-Accel-Redirect headers intended for nginx. X-Accel-Redirect requires the application to be highly coupled with the corresponding nginx configuration, and is thus too complicated to be worth supporting.

Example config.ru:

use Rainbows::Sendfile
run lambda { |env|
 path = "#{Dir.pwd}/random_blob"
 [ 200,
   {
     'X-Sendfile' => path,
     'Content-Type' => 'application/octet-stream'
   },
   []
 ]
}

Defined Under Namespace

Classes: Body

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#app ⇒ Object

Returns the value of attribute app

Returns:

  • (Object) —

    the current value of app



49
50
51
# File 'lib/rainbows/sendfile.rb', line 49

def app
  @app
end

Instance Method Details

#call(env) ⇒ Object

:nodoc:



72
73
74
75
76
77
78
79
# File 'lib/rainbows/sendfile.rb', line 72

def call(env) # :nodoc:
  status, headers, body = app.call(env)
  headers = Rack::Utils::HeaderHash.new(headers) unless Hash === headers
  if path = headers.delete('X-Sendfile'.freeze)
    body = Body.new(path, headers) unless body.respond_to?(:to_path)
  end
  [ status, headers, body ]
end