Class: Rainbows::MaxBody

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

Overview

Middleware used to enforce client_max_body_size for TeeInput users.

There is no need to configure this middleware manually, it will automatically be configured for you based on the client_max_body_size setting.

For more fine-grained control, you may also define it per-endpoint in your Rack config.ru like this:

map "/limit_1M" do
  use Rainbows::MaxBody, 1024*1024
  run MyApp
end
map "/limit_10M" do
  use Rainbows::MaxBody, 1024*1024*10
  run MyApp
end

This is only compatible with concurrency models that expose a streaming “rack.input” to the Rack application. Thus it is NOT compatible with any of the following as they fully buffer the request body before the application dispatch:

  • :Coolio

  • :CoolioThreadPool

  • :CoolioThreadSpawn

  • :Epoll

  • :EventMachine

  • :NeverBlock

  • :Rev

  • :RevThreadPool

  • :RevThreadSpawn

  • :XEpoll

However, the global Rainbows::Configurator#client_max_body_size is compatible with all concurrency models Rainbows! supports.

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(app, limit = nil) ⇒ MaxBody

This is automatically called when used with Rack::Builder#use



42
43
44
45
46
47
48
49
# File 'lib/rainbows/max_body.rb', line 42

def initialize(app, limit = nil)
  case limit
  when Integer, nil
  else
    raise ArgumentError, "limit not an Integer"
  end
  @app, @limit = app, limit
end

Class Method Details

.setupObject

this is called after forking, so it won’t ever affect the master if it’s reconfigured



67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/rainbows/max_body.rb', line 67

def self.setup # :nodoc:
  Rainbows.server.client_max_body_size or return
  case Rainbows.server.use
  when :Rev, :Coolio, :EventMachine, :NeverBlock,
       :RevThreadSpawn, :RevThreadPool,
       :CoolioThreadSpawn, :CoolioThreadPool,
       :Epoll, :XEpoll
    return
  end

  # force ourselves to the outermost middleware layer
  Rainbows.server.app = self.new(Rainbows.server.app)
end

Instance Method Details

#call(env) ⇒ Object

our main Rack middleware endpoint



52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/rainbows/max_body.rb', line 52

def call(env)
  @limit = Rainbows.server.client_max_body_size if nil == @limit
  catch(:rainbows_EFBIG) do
    len = env['CONTENT_LENGTH']
    if len && len.to_i > @limit
      return err
    elsif /\Achunked\z/i =~ env['HTTP_TRANSFER_ENCODING']
      limit_input!(env)
    end
    @app.call(env)
  end || err
end

#errObject

Rack response returned when there’s an error



82
83
84
# File 'lib/rainbows/max_body.rb', line 82

def err # :nodoc:
  [ 413, { 'Content-Length' => '0', 'Content-Type' => 'text/plain' }, [] ]
end

#limit_input!(env) ⇒ Object



86
87
88
89
90
# File 'lib/rainbows/max_body.rb', line 86

def limit_input!(env)
  input = env['rack.input']
  klass = input.respond_to?(:rewind) ? RewindableWrapper : Wrapper
  env['rack.input'] = klass.new(input, @limit)
end