rainbows 3.2.0 → 3.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +1 -0
- data/COPYING +617 -282
- data/Documentation/comparison.haml +81 -24
- data/FAQ +3 -0
- data/GIT-VERSION-GEN +1 -1
- data/LICENSE +14 -5
- data/README +10 -9
- data/Sandbox +25 -0
- data/TODO +2 -22
- data/lib/rainbows.rb +50 -49
- data/lib/rainbows/client.rb +6 -5
- data/lib/rainbows/configurator.rb +191 -37
- data/lib/rainbows/const.rb +1 -1
- data/lib/rainbows/coolio.rb +4 -1
- data/lib/rainbows/coolio/client.rb +2 -2
- data/lib/rainbows/coolio/heartbeat.rb +2 -1
- data/lib/rainbows/coolio_fiber_spawn.rb +12 -7
- data/lib/rainbows/coolio_thread_pool.rb +19 -10
- data/lib/rainbows/coolio_thread_spawn.rb +3 -0
- data/lib/rainbows/epoll.rb +27 -5
- data/lib/rainbows/epoll/client.rb +3 -3
- data/lib/rainbows/ev_core.rb +2 -1
- data/lib/rainbows/event_machine.rb +4 -0
- data/lib/rainbows/event_machine/client.rb +2 -1
- data/lib/rainbows/fiber.rb +5 -0
- data/lib/rainbows/fiber/base.rb +1 -0
- data/lib/rainbows/fiber/coolio/methods.rb +0 -1
- data/lib/rainbows/fiber/io.rb +10 -6
- data/lib/rainbows/fiber/io/pipe.rb +6 -1
- data/lib/rainbows/fiber/io/socket.rb +6 -1
- data/lib/rainbows/fiber_pool.rb +12 -7
- data/lib/rainbows/fiber_spawn.rb +11 -6
- data/lib/rainbows/http_server.rb +55 -59
- data/lib/rainbows/join_threads.rb +4 -0
- data/lib/rainbows/max_body.rb +29 -10
- data/lib/rainbows/never_block.rb +7 -10
- data/lib/rainbows/pool_size.rb +14 -0
- data/lib/rainbows/process_client.rb +23 -1
- data/lib/rainbows/queue_pool.rb +8 -6
- data/lib/rainbows/response.rb +12 -11
- data/lib/rainbows/revactor.rb +14 -7
- data/lib/rainbows/revactor/client.rb +2 -2
- data/lib/rainbows/stream_file.rb +11 -4
- data/lib/rainbows/thread_pool.rb +12 -28
- data/lib/rainbows/thread_spawn.rb +14 -13
- data/lib/rainbows/thread_timeout.rb +118 -30
- data/lib/rainbows/writer_thread_pool/client.rb +1 -1
- data/lib/rainbows/writer_thread_spawn/client.rb +2 -2
- data/lib/rainbows/xepoll.rb +13 -5
- data/lib/rainbows/xepoll/client.rb +19 -17
- data/lib/rainbows/xepoll_thread_pool.rb +82 -0
- data/lib/rainbows/xepoll_thread_pool/client.rb +129 -0
- data/lib/rainbows/xepoll_thread_spawn.rb +58 -0
- data/lib/rainbows/xepoll_thread_spawn/client.rb +121 -0
- data/pkg.mk +4 -0
- data/rainbows.gemspec +4 -1
- data/t/GNUmakefile +5 -1
- data/t/client_header_buffer_size.ru +5 -0
- data/t/simple-http_XEpollThreadPool.ru +10 -0
- data/t/simple-http_XEpollThreadSpawn.ru +10 -0
- data/t/t0022-copy_stream-byte-range.sh +1 -15
- data/t/t0026-splice-copy_stream-byte-range.sh +25 -0
- data/t/t0027-nil-copy_stream.sh +60 -0
- data/t/t0041-optional-pool-size.sh +2 -2
- data/t/t0042-client_header_buffer_size.sh +65 -0
- data/t/t9100-thread-timeout.sh +1 -6
- data/t/t9101-thread-timeout-threshold.sh +1 -6
- data/t/test-lib.sh +58 -0
- data/t/test_isolate.rb +9 -3
- metadata +47 -16
@@ -10,7 +10,7 @@ module Rainbows::Epoll::Client
|
|
10
10
|
OUT = SleepyPenguin::Epoll::OUT | SleepyPenguin::Epoll::ET
|
11
11
|
KATO = {}
|
12
12
|
KATO.compare_by_identity if KATO.respond_to?(:compare_by_identity)
|
13
|
-
|
13
|
+
Rainbows.config!(self, :keepalive_timeout)
|
14
14
|
EP = Rainbows::Epoll::EP
|
15
15
|
@@last_expire = Time.now
|
16
16
|
|
@@ -33,7 +33,7 @@ module Rainbows::Epoll::Client
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def on_readable
|
36
|
-
case rv = kgio_tryread(
|
36
|
+
case rv = kgio_tryread(CLIENT_HEADER_BUFFER_SIZE, RBUF)
|
37
37
|
when String
|
38
38
|
on_read(rv)
|
39
39
|
return if @wr_queue[0] || closed?
|
@@ -226,7 +226,7 @@ module Rainbows::Epoll::Client
|
|
226
226
|
else # nil => EOF
|
227
227
|
return pipe.close # nil
|
228
228
|
end while true
|
229
|
-
rescue
|
229
|
+
rescue
|
230
230
|
pipe.close
|
231
231
|
raise
|
232
232
|
end
|
data/lib/rainbows/ev_core.rb
CHANGED
@@ -9,6 +9,7 @@ module Rainbows::EvCore
|
|
9
9
|
autoload :CapInput, 'rainbows/ev_core/cap_input'
|
10
10
|
RBUF = ""
|
11
11
|
Z = "".freeze
|
12
|
+
Rainbows.config!(self, :client_header_buffer_size)
|
12
13
|
|
13
14
|
# Apps may return this Rack response: AsyncResponse = [ -1, {}, [] ]
|
14
15
|
ASYNC_CALLBACK = "async.callback".freeze
|
@@ -132,7 +133,7 @@ module Rainbows::EvCore
|
|
132
133
|
end
|
133
134
|
|
134
135
|
def mkinput
|
135
|
-
max = Rainbows.
|
136
|
+
max = Rainbows.server.client_max_body_size
|
136
137
|
len = @hp.content_length
|
137
138
|
if len
|
138
139
|
if max && (len > max)
|
@@ -40,6 +40,10 @@ EM::VERSION >= '0.12.10' or abort 'eventmachine 0.12.10 is required'
|
|
40
40
|
# the Rack application to process data as it arrives. This means
|
41
41
|
# "rack.input" will be fully buffered in memory or to a temporary file
|
42
42
|
# before the application is entered.
|
43
|
+
#
|
44
|
+
# === RubyGem Requirements
|
45
|
+
#
|
46
|
+
# * event_machine 0.12.10
|
43
47
|
module Rainbows::EventMachine
|
44
48
|
autoload :ResponsePipe, 'rainbows/event_machine/response_pipe'
|
45
49
|
autoload :ResponseChunkPipe, 'rainbows/event_machine/response_chunk_pipe'
|
@@ -2,6 +2,7 @@
|
|
2
2
|
# :enddoc:
|
3
3
|
class Rainbows::EventMachine::Client < EM::Connection
|
4
4
|
include Rainbows::EvCore
|
5
|
+
Rainbows.config!(self, :keepalive_timeout)
|
5
6
|
|
6
7
|
def initialize(io)
|
7
8
|
@_io = io
|
@@ -87,7 +88,7 @@ class Rainbows::EventMachine::Client < EM::Connection
|
|
87
88
|
if alive
|
88
89
|
if @deferred.nil?
|
89
90
|
if @buf.empty?
|
90
|
-
set_comm_inactivity_timeout(
|
91
|
+
set_comm_inactivity_timeout(KEEPALIVE_TIMEOUT)
|
91
92
|
else
|
92
93
|
EM.next_tick { receive_data(nil) }
|
93
94
|
end
|
data/lib/rainbows/fiber.rb
CHANGED
@@ -8,6 +8,11 @@ end
|
|
8
8
|
# :startdoc:
|
9
9
|
|
10
10
|
# core namespace for all things that use Fibers in \Rainbows!
|
11
|
+
#
|
12
|
+
# It's generally not recommended to use any of this in your applications
|
13
|
+
# unless you're willing to accept breakage. Most of this is very
|
14
|
+
# difficult-to-use, fragile and we don't have much time to devote to
|
15
|
+
# supporting these in the future.
|
11
16
|
module Rainbows::Fiber
|
12
17
|
|
13
18
|
# :stopdoc:
|
data/lib/rainbows/fiber/base.rb
CHANGED
data/lib/rainbows/fiber/io.rb
CHANGED
@@ -1,13 +1,18 @@
|
|
1
1
|
# -*- encoding: binary -*-
|
2
2
|
|
3
|
-
# A Fiber-aware IO class, gives users the illusion of a synchronous
|
4
|
-
# interface that yields away from the current Fiber whenever
|
3
|
+
# A \Fiber-aware IO class, gives users the illusion of a synchronous
|
4
|
+
# interface that yields away from the current \Fiber whenever
|
5
5
|
# the underlying descriptor is blocked on reads or write
|
6
6
|
#
|
7
|
+
# It's not recommended to use any of this in your applications
|
8
|
+
# unless you're willing to accept breakage. Most of this is very
|
9
|
+
# difficult-to-use, fragile and we don't have much time to devote to
|
10
|
+
# supporting these in the future.
|
11
|
+
#
|
7
12
|
# This is a stable, legacy interface and should be preserved for all
|
8
13
|
# future versions of Rainbows! However, new apps should use
|
9
|
-
# Rainbows::Fiber::IO::Socket or Rainbows::Fiber::IO::Pipe instead
|
10
|
-
|
14
|
+
# Rainbows::Fiber::IO::Socket or Rainbows::Fiber::IO::Pipe instead
|
15
|
+
# (or better yet, avoid any of the Rainbows::Fiber* stuff).
|
11
16
|
class Rainbows::Fiber::IO
|
12
17
|
attr_accessor :to_io
|
13
18
|
|
@@ -45,7 +50,7 @@ class Rainbows::Fiber::IO
|
|
45
50
|
end
|
46
51
|
|
47
52
|
def write(buf)
|
48
|
-
case rv = Kgio.trywrite(buf)
|
53
|
+
case rv = Kgio.trywrite(@to_io, buf)
|
49
54
|
when String
|
50
55
|
buf = rv
|
51
56
|
when :wait_writable
|
@@ -96,7 +101,6 @@ end
|
|
96
101
|
# :stopdoc:
|
97
102
|
require 'rainbows/fiber/io/methods'
|
98
103
|
require 'rainbows/fiber/io/compat'
|
99
|
-
Rainbows::Client.__send__(:include, Rainbows::Fiber::IO::Methods)
|
100
104
|
class Rainbows::Fiber::IO
|
101
105
|
include Rainbows::Fiber::IO::Compat
|
102
106
|
include Rainbows::Fiber::IO::Methods
|
@@ -1,7 +1,12 @@
|
|
1
1
|
# -*- encoding: binary -*-
|
2
2
|
# A Fiber-aware Pipe class, gives users the illusion of a synchronous
|
3
3
|
# interface that yields away from the current Fiber whenever
|
4
|
-
# the underlying descriptor is blocked on reads or write
|
4
|
+
# the underlying descriptor is blocked on reads or write.
|
5
|
+
#
|
6
|
+
# It's not recommended to use any of this in your applications
|
7
|
+
# unless you're willing to accept breakage. Most of this is very
|
8
|
+
# difficult-to-use, fragile and we don't have much time to devote to
|
9
|
+
# supporting these in the future.
|
5
10
|
class Rainbows::Fiber::IO::Pipe < Kgio::Pipe
|
6
11
|
include Rainbows::Fiber::IO::Methods
|
7
12
|
end
|
@@ -1,7 +1,12 @@
|
|
1
1
|
# -*- encoding: binary -*-
|
2
2
|
# A Fiber-aware Socket class, gives users the illusion of a synchronous
|
3
3
|
# interface that yields away from the current Fiber whenever
|
4
|
-
# the underlying descriptor is blocked on reads or write
|
4
|
+
# the underlying descriptor is blocked on reads or write.
|
5
|
+
#
|
6
|
+
# It's not recommended to use any of this in your applications
|
7
|
+
# unless you're willing to accept breakage. Most of this is very
|
8
|
+
# difficult-to-use, fragile and we don't have much time to devote to
|
9
|
+
# supporting these in the future.
|
5
10
|
class Rainbows::Fiber::IO::Socket < Kgio::Socket
|
6
11
|
include Rainbows::Fiber::IO::Methods
|
7
12
|
end
|
data/lib/rainbows/fiber_pool.rb
CHANGED
@@ -3,13 +3,18 @@ require 'rainbows/fiber'
|
|
3
3
|
|
4
4
|
# A Fiber-based concurrency model for Ruby 1.9. This uses a pool of
|
5
5
|
# Fibers to handle client IO to run the application and the root Fiber
|
6
|
-
# for scheduling and connection acceptance.
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
# the
|
6
|
+
# for scheduling and connection acceptance.
|
7
|
+
#
|
8
|
+
# This concurrency model is difficult to use with existing applications,
|
9
|
+
# lacks third-party support, and is thus NOT recommended.
|
10
|
+
#
|
11
|
+
# The pool size is equal to the number of +worker_connections+.
|
12
|
+
# Compared to the ThreadPool model, Fibers are very cheap in terms of
|
13
|
+
# memory usage so you can have more active connections. This model
|
14
|
+
# supports a streaming "rack.input" with lightweight concurrency.
|
15
|
+
# Applications are strongly advised to wrap all slow IO objects
|
16
|
+
# (sockets, pipes) using the Rainbows::Fiber::IO class whenever
|
17
|
+
# possible.
|
13
18
|
module Rainbows::FiberPool
|
14
19
|
include Rainbows::Fiber::Base
|
15
20
|
|
data/lib/rainbows/fiber_spawn.rb
CHANGED
@@ -1,12 +1,17 @@
|
|
1
1
|
# -*- encoding: binary -*-
|
2
2
|
require 'rainbows/fiber'
|
3
3
|
|
4
|
-
# Simple Fiber-based concurrency model for 1.9. This spawns a new
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
4
|
+
# Simple Fiber-based concurrency model for 1.9. This spawns a new Fiber
|
5
|
+
# for every incoming client connection and the root Fiber for scheduling
|
6
|
+
# and connection acceptance.
|
7
|
+
#
|
8
|
+
# This concurrency model is difficult to use with existing applications,
|
9
|
+
# lacks third-party support, and is thus NOT recommended.
|
10
|
+
#
|
11
|
+
# This exports a streaming "rack.input" with lightweight concurrency.
|
12
|
+
# Applications are strongly advised to wrap all slow IO objects
|
13
|
+
# (sockets, pipes) using the Rainbows::Fiber::IO class whenever
|
14
|
+
# possible.
|
10
15
|
module Rainbows::FiberSpawn
|
11
16
|
include Rainbows::Fiber::Base
|
12
17
|
|
data/lib/rainbows/http_server.rb
CHANGED
@@ -2,6 +2,13 @@
|
|
2
2
|
# :enddoc:
|
3
3
|
|
4
4
|
class Rainbows::HttpServer < Unicorn::HttpServer
|
5
|
+
attr_accessor :copy_stream
|
6
|
+
attr_accessor :worker_connections
|
7
|
+
attr_accessor :keepalive_timeout
|
8
|
+
attr_accessor :client_header_buffer_size
|
9
|
+
attr_accessor :client_max_body_size
|
10
|
+
attr_reader :use
|
11
|
+
|
5
12
|
def self.setup(block)
|
6
13
|
Rainbows.server.instance_eval(&block)
|
7
14
|
end
|
@@ -9,9 +16,9 @@ class Rainbows::HttpServer < Unicorn::HttpServer
|
|
9
16
|
def initialize(app, options)
|
10
17
|
Rainbows.server = self
|
11
18
|
@logger = Unicorn::Configurator::DEFAULTS[:logger]
|
12
|
-
|
13
|
-
defined?(@use) or use
|
14
|
-
@worker_connections ||=
|
19
|
+
super(app, options)
|
20
|
+
defined?(@use) or self.use = Rainbows::Base
|
21
|
+
@worker_connections ||= @use == :Base ? 1 : 50
|
15
22
|
end
|
16
23
|
|
17
24
|
def reopen_worker_logs(worker_nr)
|
@@ -33,80 +40,69 @@ class Rainbows::HttpServer < Unicorn::HttpServer
|
|
33
40
|
end
|
34
41
|
|
35
42
|
def load_config!
|
36
|
-
use :Base
|
37
|
-
Rainbows.keepalive_timeout = 5
|
38
|
-
Rainbows.max_bytes = 1024 * 1024
|
39
|
-
@worker_connections = nil
|
40
43
|
super
|
41
|
-
@worker_connections
|
44
|
+
@worker_connections = 1 if @use == :Base
|
45
|
+
end
|
46
|
+
|
47
|
+
def worker_loop(worker)
|
48
|
+
Rainbows.forked = true
|
49
|
+
orig = method(:worker_loop)
|
50
|
+
extend(Rainbows.const_get(@use))
|
51
|
+
m = method(:worker_loop)
|
52
|
+
orig == m ? super(worker) : worker_loop(worker)
|
42
53
|
end
|
43
54
|
|
44
|
-
def
|
45
|
-
#
|
46
|
-
|
47
|
-
|
55
|
+
def spawn_missing_workers
|
56
|
+
# 5: std{in,out,err} + heartbeat FD + per-process listener
|
57
|
+
nofile = 5 + @worker_connections + LISTENERS.size
|
58
|
+
trysetrlimit(:RLIMIT_NOFILE, nofile)
|
59
|
+
|
60
|
+
case @use
|
61
|
+
when :ThreadSpawn, :ThreadPool, :ActorSpawn,
|
62
|
+
:CoolioThreadSpawn, :RevThreadSpawn,
|
63
|
+
:XEpollThreadSpawn, :WriterThreadPool, :WriterThreadSpawn
|
64
|
+
trysetrlimit(:RLIMIT_NPROC, @worker_connections + LISTENERS.size + 1)
|
65
|
+
when :XEpollThreadPool, :CoolioThreadPool
|
66
|
+
trysetrlimit(:RLIMIT_NPROC, Rainbows::O[:pool_size] + LISTENERS.size + 1)
|
48
67
|
end
|
49
68
|
super
|
50
69
|
end
|
51
70
|
|
52
|
-
def
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
logger.
|
58
|
-
|
59
|
-
|
71
|
+
def trysetrlimit(resource, want)
|
72
|
+
var = Process.const_get(resource)
|
73
|
+
cur, max = Process.getrlimit(var)
|
74
|
+
cur <= want and Process.setrlimit(var, cur = max > want ? max : want)
|
75
|
+
if cur == want
|
76
|
+
@logger.warn "#{resource} rlim_cur=#{cur} is barely enough"
|
77
|
+
@logger.warn "#{svc} may monopolize resources dictated by #{resource}" \
|
78
|
+
" and leave none for your app"
|
60
79
|
end
|
80
|
+
rescue => e
|
81
|
+
@logger.error e.message
|
82
|
+
@logger.error "#{resource} needs to be increased to >=#{want} before" \
|
83
|
+
" starting #{svc}"
|
84
|
+
end
|
61
85
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
else; raise ArgumentError, "can't handle option: #{opt.inspect}"
|
69
|
-
end
|
70
|
-
end
|
71
|
-
mod.setup if mod.respond_to?(:setup)
|
86
|
+
def svc
|
87
|
+
File.basename($0)
|
88
|
+
end
|
89
|
+
|
90
|
+
def use=(mod)
|
91
|
+
@use = mod.to_s.split(/::/)[-1].to_sym
|
72
92
|
new_defaults = {
|
73
|
-
'rainbows.model' =>
|
74
|
-
'rack.multithread' => !!(
|
93
|
+
'rainbows.model' => @use,
|
94
|
+
'rack.multithread' => !!(mod.to_s =~ /Thread/),
|
75
95
|
'rainbows.autochunk' => [:Coolio,:Rev,:Epoll,:XEpoll,
|
76
96
|
:EventMachine,:NeverBlock].include?(@use),
|
77
97
|
}
|
78
98
|
Rainbows::Const::RACK_DEFAULTS.update(new_defaults)
|
79
99
|
end
|
80
100
|
|
81
|
-
def
|
82
|
-
return @worker_connections if args.empty?
|
83
|
-
nr = args[0]
|
84
|
-
(Integer === nr && nr > 0) or
|
85
|
-
raise ArgumentError, "worker_connections must be a positive Integer"
|
86
|
-
@worker_connections = nr
|
87
|
-
end
|
88
|
-
|
89
|
-
def keepalive_timeout(nr)
|
90
|
-
(Integer === nr && nr >= 0) or
|
91
|
-
raise ArgumentError, "keepalive_timeout must be a non-negative Integer"
|
92
|
-
Rainbows.keepalive_timeout = nr
|
93
|
-
end
|
94
|
-
|
95
|
-
def keepalive_requests(nr)
|
96
|
-
Integer === nr or
|
97
|
-
raise ArgumentError, "keepalive_requests must be a non-negative Integer"
|
101
|
+
def keepalive_requests=(nr)
|
98
102
|
Unicorn::HttpRequest.keepalive_requests = nr
|
99
103
|
end
|
100
104
|
|
101
|
-
def
|
102
|
-
|
103
|
-
case nr
|
104
|
-
when nil
|
105
|
-
when Integer
|
106
|
-
nr >= 0 or raise ArgumentError, err
|
107
|
-
else
|
108
|
-
raise ArgumentError, err
|
109
|
-
end
|
110
|
-
Rainbows.max_bytes = nr
|
105
|
+
def keepalive_requests
|
106
|
+
Unicorn::HttpRequest.keepalive_requests
|
111
107
|
end
|
112
108
|
end
|
@@ -5,9 +5,13 @@ module Rainbows::JoinThreads
|
|
5
5
|
|
6
6
|
# blocking acceptor threads must be forced to run
|
7
7
|
def self.acceptors(threads)
|
8
|
+
expire = Time.now + Rainbows.server.timeout
|
8
9
|
threads.delete_if do |thr|
|
9
10
|
Rainbows.tick
|
10
11
|
begin
|
12
|
+
# blocking accept() may not wake up properly
|
13
|
+
thr.raise(Errno::EINTR) if Time.now > expire && thr.stop?
|
14
|
+
|
11
15
|
thr.run
|
12
16
|
thr.join(0.01)
|
13
17
|
rescue
|
data/lib/rainbows/max_body.rb
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
# automatically be configured for you based on the client_max_body_size
|
7
7
|
# setting.
|
8
8
|
#
|
9
|
-
# For more fine-grained
|
9
|
+
# For more fine-grained control, you may also define it per-endpoint in
|
10
10
|
# your Rack config.ru like this:
|
11
11
|
#
|
12
12
|
# map "/limit_1M" do
|
@@ -17,16 +17,34 @@
|
|
17
17
|
# use Rainbows::MaxBody, 1024*1024*10
|
18
18
|
# run MyApp
|
19
19
|
# end
|
20
|
-
|
20
|
+
#
|
21
|
+
# This is only compatible with concurrency models that expose a streaming
|
22
|
+
# "rack.input" to the Rack application. Thus it is NOT compatible with
|
23
|
+
# any of the following as they fully buffer the request body before
|
24
|
+
# the application dispatch:
|
25
|
+
#
|
26
|
+
# * :Coolio
|
27
|
+
# * :CoolioThreadPool
|
28
|
+
# * :CoolioThreadSpawn
|
29
|
+
# * :Epoll
|
30
|
+
# * :EventMachine
|
31
|
+
# * :NeverBlock
|
32
|
+
# * :Rev
|
33
|
+
# * :RevThreadPool
|
34
|
+
# * :RevThreadSpawn
|
35
|
+
# * :XEpoll
|
36
|
+
#
|
37
|
+
# However, the global Rainbows::Configurator#client_max_body_size is compatible
|
38
|
+
# with all concurrency models \Rainbows! supports.
|
21
39
|
class Rainbows::MaxBody
|
22
40
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
41
|
+
# This is automatically called when used with Rack::Builder#use
|
42
|
+
def initialize(app, limit = nil)
|
43
|
+
case limit
|
44
|
+
when Integer, nil
|
45
|
+
else
|
46
|
+
raise ArgumentError, "limit not an Integer"
|
47
|
+
end
|
30
48
|
@app, @limit = app, limit
|
31
49
|
end
|
32
50
|
|
@@ -37,6 +55,7 @@ class Rainbows::MaxBody
|
|
37
55
|
|
38
56
|
# our main Rack middleware endpoint
|
39
57
|
def call(env)
|
58
|
+
@limit = Rainbows.server.client_max_body_size if nil == @limit
|
40
59
|
catch(:rainbows_EFBIG) do
|
41
60
|
len = env[CONTENT_LENGTH]
|
42
61
|
if len && len.to_i > @limit
|
@@ -51,7 +70,7 @@ class Rainbows::MaxBody
|
|
51
70
|
# this is called after forking, so it won't ever affect the master
|
52
71
|
# if it's reconfigured
|
53
72
|
def self.setup # :nodoc:
|
54
|
-
Rainbows.
|
73
|
+
Rainbows.server.client_max_body_size or return
|
55
74
|
case Rainbows.server.use
|
56
75
|
when :Rev, :Coolio, :EventMachine, :NeverBlock,
|
57
76
|
:RevThreadSpawn, :RevThreadPool,
|