1 # -*- encoding: binary -*-
3 # Middleware used to enforce client_max_body_size for TeeInput users.
5 # There is no need to configure this middleware manually, it will
6 # automatically be configured for you based on the client_max_body_size
9 # For more fine-grained conrol, you may also define it per-endpoint in
10 # your Rack config.ru like this:
13 # use Rainbows::MaxBody, 1024*1024
17 # use Rainbows::MaxBody, 1024*1024*10
21 class Rainbows::MaxBody
26 # use Rainbows::MaxBody, 4096
27 # run YourApplication.new
28 def initialize(app, limit = Rainbows.max_bytes)
29 Integer === limit or raise ArgumentError, "limit not an Integer"
30 @app, @limit = app, limit
34 RACK_INPUT = "rack.input".freeze
35 CONTENT_LENGTH = "CONTENT_LENGTH"
36 HTTP_TRANSFER_ENCODING = "HTTP_TRANSFER_ENCODING"
38 # our main Rack middleware endpoint
40 catch(:rainbows_EFBIG) do
41 len = env[CONTENT_LENGTH]
42 if len && len.to_i > @limit
44 elsif /\Achunked\z/i =~ env[HTTP_TRANSFER_ENCODING]
51 # this is called after forking, so it won't ever affect the master
52 # if it's reconfigured
53 def self.setup # :nodoc:
54 Rainbows.max_bytes or return
55 case Rainbows.server.use
56 when :Rev, :Coolio, :EventMachine, :NeverBlock,
57 :RevThreadSpawn, :RevThreadPool,
58 :CoolioThreadSpawn, :CoolioThreadPool,
63 # force ourselves to the outermost middleware layer
64 Rainbows.server.app = self.new(Rainbows.server.app)
67 # Rack response returned when there's an error
69 [ 413, { 'Content-Length' => '0', 'Content-Type' => 'text/plain' }, [] ]
73 input = env[RACK_INPUT]
74 klass = input.respond_to?(:rewind) ? RewindableWrapper : Wrapper
75 env[RACK_INPUT] = klass.new(input, @limit)
80 require 'rainbows/max_body/wrapper'
81 require 'rainbows/max_body/rewindable_wrapper'