1 # -*- encoding: binary -*-
3 # This module adds \Rainbows! to the
4 # {Unicorn::Configurator}[http://unicorn.bogomips.org/Unicorn/Configurator.html]
5 # \Rainbows!-specific configuration options must be inside a the Rainbows!
6 # block, otherwise Unicorn::Configurator directives may be used anywhere
10 # use :ThreadSpawn # concurrency model to use
11 # worker_connections 400
12 # keepalive_timeout 0 # zero disables keepalives entirely
13 # client_max_body_size 5*1024*1024 # 5 megabytes
14 # keepalive_requests 666 # default:100
15 # client_header_buffer_size 2 * 1024 # 2 kilobytes
18 # # the rest of the Unicorn configuration...
20 # stderr_path "/path/to/error.log"
21 # stdout_path "/path/to/output.log"
22 module Rainbows::Configurator
23 Unicorn::Configurator::DEFAULTS.merge!({
24 :use => Rainbows::Base,
25 :worker_connections => 50,
26 :keepalive_timeout => 5,
27 :keepalive_requests => 100,
28 :client_max_body_size => 1024 * 1024,
29 :client_header_buffer_size => 1024,
30 :client_max_header_size => 112 * 1024,
31 :copy_stream => IO.respond_to?(:copy_stream) ? IO : false,
34 # Configures \Rainbows! with a given concurrency model to +use+ and
35 # a +worker_connections+ upper-bound. This method should be called
36 # inside a Unicorn/\Rainbows! configuration file.
38 # All other methods in Rainbows::Configurator must be called
41 block_given? or raise ArgumentError, "Rainbows! requires a block"
49 @block or abort "must be inside a Rainbows! block"
52 # This limits the number of connected clients per-process. The total
53 # number of clients on a server is +worker_processes+ * +worker_connections+.
55 # This option has no effect with the Base concurrency model, which is
59 def worker_connections(clients)
61 set_int(:worker_connections, clients, 1)
64 # Select a concurrency model for use with \Rainbows!. You must select
65 # this with a Symbol (prefixed with ":"). Thus if you wish to select
66 # the Rainbows::ThreadSpawn concurrency model, you would use:
72 # See the {Summary}[link:Summary.html] document for a summary of
73 # supported concurrency models. +options+ may be specified for some
74 # concurrency models, but the majority do not support them.
76 # Default: :Base (no concurrency)
77 def use(model, *options)
80 Rainbows.const_get(model)
82 warn "error loading #{model.inspect}: #{e}"
83 e.backtrace.each { |l| warn l }
84 abort "concurrency model #{model.inspect} not supported"
86 Module === mod or abort "concurrency model #{model.inspect} not supported"
90 Rainbows::O.merge!(opt)
92 Rainbows::O[opt] = true
94 abort "cannot handle option: #{opt.inspect} in #{options.inspect}"
97 mod.setup if mod.respond_to?(:setup)
101 # Sets the value (in seconds) the server will wait for a client in
102 # between requests. The default value should be enough under most
103 # conditions for browsers to render the page and start retrieving
106 # Setting this value to +0+ disables keepalive entirely
109 def keepalive_timeout(seconds)
111 set_int(:keepalive_timeout, seconds, 0)
114 # This limits the number of requests which can be made over a keep-alive
115 # connection. This is used to prevent single client from monopolizing
116 # the server and to improve fairness when load-balancing across multiple
117 # machines by forcing a client to reconnect. This may be helpful
118 # in mitigating some denial-of-service attacks.
120 # Default: 100 requests
121 def keepalive_requests(count)
125 set[:keepalive_requests] = count
127 abort "not an integer or nil: keepalive_requests=#{count.inspect}"
131 # Limits the maximum size of a request body for all requests.
132 # Setting this to +nil+ disables the maximum size check.
134 # Default: 1 megabyte (1048576 bytes)
136 # If you want endpoint-specific upload limits and use a
137 # "rack.input"-streaming concurrency model, see the Rainbows::MaxBody
138 def client_max_body_size(bytes)
140 err = "client_max_body_size must be nil or a non-negative Integer"
144 bytes >= 0 or abort err
148 set[:client_max_body_size] = bytes
151 # Limits the maximum size of a request header for all requests.
153 # Default: 112 kilobytes (114688 bytes)
155 # Lowering this will lower worst-case memory usage and mitigate some
156 # denial-of-service attacks. This should be larger than
157 # client_header_buffer_size.
158 def client_max_header_size(bytes)
160 set_int(:client_max_header_size, bytes, 8)
163 # This governs the amount of memory allocated for an individual read(2) or
164 # recv(2) system call when reading headers. Applications that make minimal
165 # use of cookies should not increase this from the default.
167 # Rails applications using session cookies may want to increase this to
168 # 2048 bytes or more depending on expected request sizes.
170 # Increasing this will increase overall memory usage to your application,
171 # as you will need at least this amount of memory for every connected client.
173 # Default: 1024 bytes
174 def client_header_buffer_size(bytes)
176 set_int(:client_header_buffer_size, bytes, 1)
179 # Allows overriding the +klass+ where the +copy_stream+ method is
180 # used to do efficient copying of regular files, pipes, and sockets.
182 # This is only used with multi-threaded concurrency models:
186 # * WriterThreadSpawn
188 # * XEpollThreadSpawn
191 # Due to existing {bugs}[http://redmine.ruby-lang.org/search?q=copy_stream]
192 # in the Ruby IO.copy_stream implementation, \Rainbows! uses the
193 # "sendfile" RubyGem that instead of copy_stream to transfer regular files
194 # to clients. The "sendfile" RubyGem also supports more operating systems,
195 # and works with more concurrency models.
197 # Recent Linux 2.6 users may override this with "IO::Splice" from the
198 # "io_splice" RubyGem:
200 # require "io/splice"
202 # copy_stream IO::Splice
205 # Keep in mind that splice(2) itself is a relatively new system call
206 # and has been buggy in many older Linux kernels. If you're proxying
207 # the output of sockets to the client, be sure to use "io_splice"
208 # 4.1.1 or later to avoid stalling responses.
210 # Default: IO on Ruby 1.9+, false otherwise
211 def copy_stream(klass)
213 if klass && ! klass.respond_to?(:copy_stream)
214 abort "#{klass} must respond to `copy_stream' or be `false'"
216 set[:copy_stream] = klass
221 # inject the Rainbows! method into Unicorn::Configurator
222 Unicorn::Configurator.__send__(:include, Rainbows::Configurator)