puma-simon 3.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (157) hide show
  1. checksums.yaml +7 -0
  2. data/.github/issue_template.md +20 -0
  3. data/.gitignore +18 -0
  4. data/.hoeignore +12 -0
  5. data/.travis.yml +29 -0
  6. data/DEPLOYMENT.md +91 -0
  7. data/Gemfile +12 -0
  8. data/History.md +1254 -0
  9. data/LICENSE +26 -0
  10. data/Manifest.txt +78 -0
  11. data/README.md +353 -0
  12. data/Rakefile +158 -0
  13. data/Release.md +9 -0
  14. data/bin/puma +10 -0
  15. data/bin/puma-wild +31 -0
  16. data/bin/pumactl +12 -0
  17. data/docs/nginx.md +80 -0
  18. data/docs/signals.md +43 -0
  19. data/docs/systemd.md +197 -0
  20. data/examples/CA/cacert.pem +23 -0
  21. data/examples/CA/newcerts/cert_1.pem +19 -0
  22. data/examples/CA/newcerts/cert_2.pem +19 -0
  23. data/examples/CA/private/cakeypair.pem +30 -0
  24. data/examples/CA/serial +1 -0
  25. data/examples/config.rb +200 -0
  26. data/examples/plugins/redis_stop_puma.rb +46 -0
  27. data/examples/puma/cert_puma.pem +19 -0
  28. data/examples/puma/client-certs/ca.crt +19 -0
  29. data/examples/puma/client-certs/ca.key +27 -0
  30. data/examples/puma/client-certs/client.crt +19 -0
  31. data/examples/puma/client-certs/client.key +27 -0
  32. data/examples/puma/client-certs/client_expired.crt +19 -0
  33. data/examples/puma/client-certs/client_expired.key +27 -0
  34. data/examples/puma/client-certs/client_unknown.crt +19 -0
  35. data/examples/puma/client-certs/client_unknown.key +27 -0
  36. data/examples/puma/client-certs/generate.rb +78 -0
  37. data/examples/puma/client-certs/keystore.jks +0 -0
  38. data/examples/puma/client-certs/server.crt +19 -0
  39. data/examples/puma/client-certs/server.key +27 -0
  40. data/examples/puma/client-certs/server.p12 +0 -0
  41. data/examples/puma/client-certs/unknown_ca.crt +19 -0
  42. data/examples/puma/client-certs/unknown_ca.key +27 -0
  43. data/examples/puma/csr_puma.pem +11 -0
  44. data/examples/puma/keystore.jks +0 -0
  45. data/examples/puma/puma_keypair.pem +15 -0
  46. data/examples/qc_config.rb +13 -0
  47. data/ext/puma_http11/PumaHttp11Service.java +17 -0
  48. data/ext/puma_http11/ext_help.h +15 -0
  49. data/ext/puma_http11/extconf.rb +15 -0
  50. data/ext/puma_http11/http11_parser.c +1069 -0
  51. data/ext/puma_http11/http11_parser.h +65 -0
  52. data/ext/puma_http11/http11_parser.java.rl +161 -0
  53. data/ext/puma_http11/http11_parser.rl +147 -0
  54. data/ext/puma_http11/http11_parser_common.rl +54 -0
  55. data/ext/puma_http11/io_buffer.c +155 -0
  56. data/ext/puma_http11/mini_ssl.c +457 -0
  57. data/ext/puma_http11/org/jruby/puma/Http11.java +234 -0
  58. data/ext/puma_http11/org/jruby/puma/Http11Parser.java +473 -0
  59. data/ext/puma_http11/org/jruby/puma/MiniSSL.java +339 -0
  60. data/ext/puma_http11/puma_http11.c +500 -0
  61. data/gemfiles/2.1-Gemfile +12 -0
  62. data/lib/puma.rb +15 -0
  63. data/lib/puma/accept_nonblock.rb +23 -0
  64. data/lib/puma/app/status.rb +66 -0
  65. data/lib/puma/binder.rb +402 -0
  66. data/lib/puma/cli.rb +220 -0
  67. data/lib/puma/client.rb +434 -0
  68. data/lib/puma/cluster.rb +510 -0
  69. data/lib/puma/commonlogger.rb +106 -0
  70. data/lib/puma/compat.rb +14 -0
  71. data/lib/puma/configuration.rb +364 -0
  72. data/lib/puma/const.rb +224 -0
  73. data/lib/puma/control_cli.rb +259 -0
  74. data/lib/puma/convenient.rb +23 -0
  75. data/lib/puma/daemon_ext.rb +31 -0
  76. data/lib/puma/delegation.rb +11 -0
  77. data/lib/puma/detect.rb +13 -0
  78. data/lib/puma/dsl.rb +486 -0
  79. data/lib/puma/events.rb +152 -0
  80. data/lib/puma/io_buffer.rb +7 -0
  81. data/lib/puma/java_io_buffer.rb +45 -0
  82. data/lib/puma/jruby_restart.rb +83 -0
  83. data/lib/puma/launcher.rb +410 -0
  84. data/lib/puma/minissl.rb +221 -0
  85. data/lib/puma/null_io.rb +42 -0
  86. data/lib/puma/plugin.rb +115 -0
  87. data/lib/puma/plugin/tmp_restart.rb +35 -0
  88. data/lib/puma/rack/backports/uri/common_193.rb +33 -0
  89. data/lib/puma/rack/builder.rb +298 -0
  90. data/lib/puma/rack/urlmap.rb +91 -0
  91. data/lib/puma/rack_default.rb +7 -0
  92. data/lib/puma/reactor.rb +210 -0
  93. data/lib/puma/runner.rb +171 -0
  94. data/lib/puma/server.rb +949 -0
  95. data/lib/puma/single.rb +112 -0
  96. data/lib/puma/state_file.rb +29 -0
  97. data/lib/puma/tcp_logger.rb +39 -0
  98. data/lib/puma/thread_pool.rb +297 -0
  99. data/lib/puma/util.rb +128 -0
  100. data/lib/rack/handler/puma.rb +78 -0
  101. data/puma.gemspec +52 -0
  102. data/test/ab_rs.rb +22 -0
  103. data/test/config.rb +2 -0
  104. data/test/config/app.rb +9 -0
  105. data/test/config/plugin.rb +1 -0
  106. data/test/config/settings.rb +2 -0
  107. data/test/config/state_file_testing_config.rb +14 -0
  108. data/test/hello-bind.ru +2 -0
  109. data/test/hello-delay.ru +3 -0
  110. data/test/hello-map.ru +3 -0
  111. data/test/hello-post.ru +4 -0
  112. data/test/hello-stuck.ru +1 -0
  113. data/test/hello-tcp.ru +5 -0
  114. data/test/hello.ru +1 -0
  115. data/test/hijack.ru +6 -0
  116. data/test/hijack2.ru +5 -0
  117. data/test/lobster.ru +4 -0
  118. data/test/shell/run.sh +24 -0
  119. data/test/shell/t1.rb +19 -0
  120. data/test/shell/t1_conf.rb +3 -0
  121. data/test/shell/t2.rb +17 -0
  122. data/test/shell/t2_conf.rb +6 -0
  123. data/test/shell/t3.rb +25 -0
  124. data/test/shell/t3_conf.rb +5 -0
  125. data/test/slow.ru +4 -0
  126. data/test/ssl_config.rb +4 -0
  127. data/test/test_app_status.rb +93 -0
  128. data/test/test_binder.rb +31 -0
  129. data/test/test_cli.rb +209 -0
  130. data/test/test_config.rb +95 -0
  131. data/test/test_events.rb +161 -0
  132. data/test/test_helper.rb +50 -0
  133. data/test/test_http10.rb +27 -0
  134. data/test/test_http11.rb +186 -0
  135. data/test/test_integration.rb +247 -0
  136. data/test/test_iobuffer.rb +39 -0
  137. data/test/test_minissl.rb +29 -0
  138. data/test/test_null_io.rb +49 -0
  139. data/test/test_persistent.rb +245 -0
  140. data/test/test_puma_server.rb +626 -0
  141. data/test/test_puma_server_ssl.rb +222 -0
  142. data/test/test_rack_handler.rb +57 -0
  143. data/test/test_rack_server.rb +138 -0
  144. data/test/test_tcp_logger.rb +39 -0
  145. data/test/test_tcp_rack.rb +36 -0
  146. data/test/test_thread_pool.rb +250 -0
  147. data/test/test_unix_socket.rb +35 -0
  148. data/test/test_web_server.rb +88 -0
  149. data/tools/jungle/README.md +9 -0
  150. data/tools/jungle/init.d/README.md +59 -0
  151. data/tools/jungle/init.d/puma +421 -0
  152. data/tools/jungle/init.d/run-puma +18 -0
  153. data/tools/jungle/upstart/README.md +61 -0
  154. data/tools/jungle/upstart/puma-manager.conf +31 -0
  155. data/tools/jungle/upstart/puma.conf +69 -0
  156. data/tools/trickletest.rb +45 -0
  157. metadata +297 -0
@@ -0,0 +1,106 @@
1
+ module Puma
2
+ # Rack::CommonLogger forwards every request to the given +app+, and
3
+ # logs a line in the
4
+ # {Apache common log format}[http://httpd.apache.org/docs/1.3/logs.html#common]
5
+ # to the +logger+.
6
+ #
7
+ # If +logger+ is nil, CommonLogger will fall back +rack.errors+, which is
8
+ # an instance of Rack::NullLogger.
9
+ #
10
+ # +logger+ can be any class, including the standard library Logger, and is
11
+ # expected to have either +write+ or +<<+ method, which accepts the CommonLogger::FORMAT.
12
+ # According to the SPEC, the error stream must also respond to +puts+
13
+ # (which takes a single argument that responds to +to_s+), and +flush+
14
+ # (which is called without arguments in order to make the error appear for
15
+ # sure)
16
+ class CommonLogger
17
+ # Common Log Format: http://httpd.apache.org/docs/1.3/logs.html#common
18
+ #
19
+ # lilith.local - - [07/Aug/2006 23:58:02 -0400] "GET / HTTP/1.1" 500 -
20
+ #
21
+ # %{%s - %s [%s] "%s %s%s %s" %d %s\n} %
22
+ FORMAT = %{%s - %s [%s] "%s %s%s %s" %d %s %0.4f\n}
23
+
24
+ HIJACK_FORMAT = %{%s - %s [%s] "%s %s%s %s" HIJACKED -1 %0.4f\n}
25
+
26
+ CONTENT_LENGTH = 'Content-Length'.freeze
27
+ PATH_INFO = 'PATH_INFO'.freeze
28
+ QUERY_STRING = 'QUERY_STRING'.freeze
29
+ REQUEST_METHOD = 'REQUEST_METHOD'.freeze
30
+
31
+ def initialize(app, logger=nil)
32
+ @app = app
33
+ @logger = logger
34
+ end
35
+
36
+ def call(env)
37
+ began_at = Time.now
38
+ status, header, body = @app.call(env)
39
+ header = Util::HeaderHash.new(header)
40
+
41
+ # If we've been hijacked, then output a special line
42
+ if env['rack.hijack_io']
43
+ log_hijacking(env, 'HIJACK', header, began_at)
44
+ else
45
+ ary = env['rack.after_reply']
46
+ ary << lambda { log(env, status, header, began_at) }
47
+ end
48
+
49
+ [status, header, body]
50
+ end
51
+
52
+ private
53
+
54
+ def log_hijacking(env, status, header, began_at)
55
+ now = Time.now
56
+
57
+ msg = HIJACK_FORMAT % [
58
+ env['HTTP_X_FORWARDED_FOR'] || env["REMOTE_ADDR"] || "-",
59
+ env["REMOTE_USER"] || "-",
60
+ now.strftime("%d/%b/%Y %H:%M:%S"),
61
+ env[REQUEST_METHOD],
62
+ env[PATH_INFO],
63
+ env[QUERY_STRING].empty? ? "" : "?#{env[QUERY_STRING]}",
64
+ env["HTTP_VERSION"],
65
+ now - began_at ]
66
+
67
+ write(msg)
68
+ end
69
+
70
+ def log(env, status, header, began_at)
71
+ now = Time.now
72
+ length = extract_content_length(header)
73
+
74
+ msg = FORMAT % [
75
+ env['HTTP_X_FORWARDED_FOR'] || env["REMOTE_ADDR"] || "-",
76
+ env["REMOTE_USER"] || "-",
77
+ now.strftime("%d/%b/%Y:%H:%M:%S %z"),
78
+ env[REQUEST_METHOD],
79
+ env[PATH_INFO],
80
+ env[QUERY_STRING].empty? ? "" : "?#{env[QUERY_STRING]}",
81
+ env["HTTP_VERSION"],
82
+ status.to_s[0..3],
83
+ length,
84
+ now - began_at ]
85
+
86
+ write(msg)
87
+ end
88
+
89
+ def write(msg)
90
+ logger = @logger || env['rack.errors']
91
+
92
+ # Standard library logger doesn't support write but it supports << which actually
93
+ # calls to write on the log device without formatting
94
+ if logger.respond_to?(:write)
95
+ logger.write(msg)
96
+ else
97
+ logger << msg
98
+ end
99
+ end
100
+
101
+ def extract_content_length(headers)
102
+ value = headers[CONTENT_LENGTH] or return '-'
103
+ value.to_s == '0' ? '-' : value
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,14 @@
1
+ # Provides code to work properly on 1.8 and 1.9
2
+
3
+ class String
4
+ unless method_defined? :bytesize
5
+ alias_method :bytesize, :size
6
+ end
7
+
8
+ unless method_defined? :byteslice
9
+ def byteslice(*arg)
10
+ enc = self.encoding
11
+ self.dup.force_encoding(Encoding::ASCII_8BIT).slice(*arg).force_encoding(enc)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,364 @@
1
+ require 'puma/rack/builder'
2
+ require 'puma/plugin'
3
+ require 'puma/const'
4
+
5
+ module Puma
6
+
7
+ module ConfigDefault
8
+ DefaultRackup = "config.ru"
9
+
10
+ DefaultTCPHost = "0.0.0.0"
11
+ DefaultTCPPort = 9292
12
+ DefaultWorkerTimeout = 60
13
+ DefaultWorkerShutdownTimeout = 30
14
+ end
15
+
16
+ class LeveledOptions
17
+ def initialize(default_options, user_options)
18
+ @cur = user_options
19
+ @set = [@cur]
20
+ @defaults = default_options.dup
21
+ end
22
+
23
+ def initialize_copy(other)
24
+ @set = @set.map { |o| o.dup }
25
+ @cur = @set.last
26
+ end
27
+
28
+ def shift
29
+ @cur = {}
30
+ @set << @cur
31
+ end
32
+
33
+ def reverse_shift
34
+ @cur = {}
35
+ @set.unshift(@cur)
36
+ end
37
+
38
+ def [](key)
39
+ @set.reverse_each do |o|
40
+ if o.key? key
41
+ return o[key]
42
+ end
43
+ end
44
+
45
+ v = @defaults[key]
46
+ if v.respond_to? :call
47
+ v.call
48
+ else
49
+ v
50
+ end
51
+ end
52
+
53
+ def fetch(key, default=nil)
54
+ val = self[key]
55
+ return val if val
56
+ default
57
+ end
58
+
59
+ attr_reader :cur
60
+
61
+ def all_of(key)
62
+ all = []
63
+
64
+ @set.each do |o|
65
+ if v = o[key]
66
+ if v.kind_of? Array
67
+ all += v
68
+ else
69
+ all << v
70
+ end
71
+ end
72
+ end
73
+
74
+ all
75
+ end
76
+
77
+ def []=(key, val)
78
+ @cur[key] = val
79
+ end
80
+
81
+ def key?(key)
82
+ @set.each do |o|
83
+ if o.key? key
84
+ return true
85
+ end
86
+ end
87
+
88
+ @default.key? key
89
+ end
90
+
91
+ def merge!(o)
92
+ o.each do |k,v|
93
+ @cur[k]= v
94
+ end
95
+ end
96
+
97
+ def flatten
98
+ options = {}
99
+
100
+ @set.each do |o|
101
+ o.each do |k,v|
102
+ options[k] ||= v
103
+ end
104
+ end
105
+
106
+ options
107
+ end
108
+
109
+ def explain
110
+ indent = ""
111
+
112
+ @set.each do |o|
113
+ o.keys.sort.each do |k|
114
+ puts "#{indent}#{k}: #{o[k].inspect}"
115
+ end
116
+
117
+ indent = " #{indent}"
118
+ end
119
+ end
120
+
121
+ def force_defaults
122
+ @defaults.each do |k,v|
123
+ if v.respond_to? :call
124
+ @defaults[k] = v.call
125
+ end
126
+ end
127
+ end
128
+ end
129
+
130
+ class Configuration
131
+ include ConfigDefault
132
+
133
+ def self.from_file(path)
134
+ cfg = new
135
+
136
+ DSL.new(cfg.options, cfg)._load_from path
137
+
138
+ return cfg
139
+ end
140
+
141
+ def initialize(options={}, &blk)
142
+ @options = LeveledOptions.new(default_options, options)
143
+
144
+ @plugins = PluginLoader.new
145
+
146
+ if blk
147
+ configure(&blk)
148
+ end
149
+ end
150
+
151
+ attr_reader :options, :plugins
152
+
153
+ def configure(&blk)
154
+ @options.shift
155
+ DSL.new(@options, self)._run(&blk)
156
+ end
157
+
158
+ def initialize_copy(other)
159
+ @conf = nil
160
+ @cli_options = nil
161
+ @options = @options.dup
162
+ end
163
+
164
+ def flatten
165
+ dup.flatten!
166
+ end
167
+
168
+ def flatten!
169
+ @options = @options.flatten
170
+ self
171
+ end
172
+
173
+ def default_options
174
+ {
175
+ :min_threads => 0,
176
+ :max_threads => 16,
177
+ :log_requests => false,
178
+ :debug => false,
179
+ :binds => ["tcp://#{DefaultTCPHost}:#{DefaultTCPPort}"],
180
+ :workers => 0,
181
+ :daemon => false,
182
+ :mode => :http,
183
+ :worker_timeout => DefaultWorkerTimeout,
184
+ :worker_boot_timeout => DefaultWorkerTimeout,
185
+ :worker_shutdown_timeout => DefaultWorkerShutdownTimeout,
186
+ :remote_address => :socket,
187
+ :tag => method(:infer_tag),
188
+ :environment => lambda { ENV['RACK_ENV'] || "development" },
189
+ :rackup => DefaultRackup,
190
+ :logger => STDOUT,
191
+ :persistent_timeout => Const::PERSISTENT_TIMEOUT
192
+ }
193
+ end
194
+
195
+ def load
196
+ files = @options.all_of(:config_files)
197
+
198
+ if files.empty?
199
+ imp = %W(config/puma/#{@options[:environment]}.rb config/puma.rb).find { |f|
200
+ File.exist?(f)
201
+ }
202
+
203
+ files << imp
204
+ elsif files == ["-"]
205
+ files = []
206
+ end
207
+
208
+ files.each do |f|
209
+ @options.reverse_shift
210
+
211
+ DSL.load @options, self, f
212
+ end
213
+ @options.shift
214
+ end
215
+
216
+ # Call once all configuration (included from rackup files)
217
+ # is loaded to flesh out any defaults
218
+ def clamp
219
+ @options.shift
220
+ @options.force_defaults
221
+ end
222
+
223
+ # Injects the Configuration object into the env
224
+ class ConfigMiddleware
225
+ def initialize(config, app)
226
+ @config = config
227
+ @app = app
228
+ end
229
+
230
+ def call(env)
231
+ env[Const::PUMA_CONFIG] = @config
232
+ @app.call(env)
233
+ end
234
+ end
235
+
236
+ # Indicate if there is a properly configured app
237
+ #
238
+ def app_configured?
239
+ @options[:app] || File.exist?(rackup)
240
+ end
241
+
242
+ def rackup
243
+ @options[:rackup]
244
+ end
245
+
246
+ # Load the specified rackup file, pull options from
247
+ # the rackup file, and set @app.
248
+ #
249
+ def app
250
+ found = options[:app] || load_rackup
251
+
252
+ if @options[:mode] == :tcp
253
+ require 'puma/tcp_logger'
254
+
255
+ logger = @options[:logger]
256
+ quiet = !@options[:log_requests]
257
+ return TCPLogger.new(logger, found, quiet)
258
+ end
259
+
260
+ if @options[:log_requests]
261
+ require 'puma/commonlogger'
262
+ logger = @options[:logger]
263
+ found = CommonLogger.new(found, logger)
264
+ end
265
+
266
+ ConfigMiddleware.new(self, found)
267
+ end
268
+
269
+ # Return which environment we're running in
270
+ def environment
271
+ @options[:environment]
272
+ end
273
+
274
+ def load_plugin(name)
275
+ @plugins.create name
276
+ end
277
+
278
+ def run_hooks(key, arg)
279
+ @options.all_of(key).each { |b| b.call arg }
280
+ end
281
+
282
+ def self.temp_path
283
+ require 'tmpdir'
284
+
285
+ t = (Time.now.to_f * 1000).to_i
286
+ "#{Dir.tmpdir}/puma-status-#{t}-#{$$}"
287
+ end
288
+
289
+ private
290
+
291
+ def infer_tag
292
+ File.basename(Dir.getwd)
293
+ end
294
+
295
+ # Load and use the normal Rack builder if we can, otherwise
296
+ # fallback to our minimal version.
297
+ def rack_builder
298
+ # Load bundler now if we can so that we can pickup rack from
299
+ # a Gemfile
300
+ if ENV.key? 'PUMA_BUNDLER_PRUNED'
301
+ begin
302
+ require 'bundler/setup'
303
+ rescue LoadError
304
+ end
305
+ end
306
+
307
+ begin
308
+ require 'rack'
309
+ require 'rack/builder'
310
+ rescue LoadError
311
+ # ok, use builtin version
312
+ return Puma::Rack::Builder
313
+ else
314
+ return ::Rack::Builder
315
+ end
316
+ end
317
+
318
+ def load_rackup
319
+ raise "Missing rackup file '#{rackup}'" unless File.exist?(rackup)
320
+
321
+ @options.shift
322
+
323
+ rack_app, rack_options = rack_builder.parse_file(rackup)
324
+ @options.merge!(rack_options)
325
+
326
+ config_ru_binds = []
327
+ rack_options.each do |k, v|
328
+ config_ru_binds << v if k.to_s.start_with?("bind")
329
+ end
330
+
331
+ @options[:binds] = config_ru_binds unless config_ru_binds.empty?
332
+
333
+ rack_app
334
+ end
335
+
336
+ def self.random_token
337
+ begin
338
+ require 'openssl'
339
+ rescue LoadError
340
+ end
341
+
342
+ count = 16
343
+
344
+ bytes = nil
345
+
346
+ if defined? OpenSSL::Random
347
+ bytes = OpenSSL::Random.random_bytes(count)
348
+ elsif File.exist?("/dev/urandom")
349
+ File.open('/dev/urandom') { |f| bytes = f.read(count) }
350
+ end
351
+
352
+ if bytes
353
+ token = ""
354
+ bytes.each_byte { |b| token << b.to_s(16) }
355
+ else
356
+ token = (0..count).to_a.map { rand(255).to_s(16) }.join
357
+ end
358
+
359
+ return token
360
+ end
361
+ end
362
+ end
363
+
364
+ require 'puma/dsl'