1 # -*- encoding: binary -*-
4 # 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
8 class MaxBody < Struct.new(:app)
10 # this is meant to be included in Rainbows::TeeInput (and derived
11 # classes) to limit body sizes
15 def initialize(socket, req, parser, buf)
16 self.len = parser.content_length
18 max = Rainbows.max_bytes # never nil, see MaxBody.setup
20 socket.write(Const::ERROR_413_RESPONSE)
22 raise IOError, "Content-Length too big: #{len} > #{max}", []
31 parser.filter_body(buf2, buf) and finalize_input
32 buf2.size > max and raise IOError, "chunked request body too big", []
34 self.tmp = len && len < Const::MAX_BODY ? StringIO.new("") : Util.tmpio
45 if rv && ((@max_body -= rv.size) < 0)
46 # make HttpParser#keepalive? => false to force an immediate disconnect
56 # this is called after forking, so it won't ever affect the master
57 # if it's reconfigured
59 Rainbows.max_bytes or return
61 when :Rev, :EventMachine, :NeverBlock
65 TeeInput.class_eval { include Limit }
67 # force ourselves to the outermost middleware layer
68 G.server.app = MaxBody.new(G.server.app)
71 # Rack response returned when there's an error
73 [ 413, [ %w(Content-Length 0), %w(Content-Type text/plain) ], [] ]
76 # our main Rack middleware endpoint
78 catch(:rainbows_EFBIG) { app.call(env) } || err(env)