puma 5.6.9-java → 6.0.0-java
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of puma might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/History.md +96 -28
- data/LICENSE +0 -0
- data/README.md +21 -17
- data/bin/puma-wild +1 -1
- data/docs/architecture.md +0 -0
- data/docs/compile_options.md +34 -0
- data/docs/deployment.md +0 -0
- data/docs/fork_worker.md +1 -3
- data/docs/images/puma-connection-flow-no-reactor.png +0 -0
- data/docs/images/puma-connection-flow.png +0 -0
- data/docs/images/puma-general-arch.png +0 -0
- data/docs/jungle/README.md +0 -0
- data/docs/jungle/rc.d/README.md +0 -0
- data/docs/jungle/rc.d/puma.conf +0 -0
- data/docs/kubernetes.md +0 -0
- data/docs/nginx.md +0 -0
- data/docs/plugins.md +0 -0
- data/docs/rails_dev_mode.md +0 -0
- data/docs/restart.md +0 -0
- data/docs/signals.md +0 -0
- data/docs/stats.md +0 -0
- data/docs/systemd.md +0 -0
- data/docs/testing_benchmarks_local_files.md +150 -0
- data/docs/testing_test_rackup_ci_files.md +36 -0
- data/ext/puma_http11/PumaHttp11Service.java +0 -0
- data/ext/puma_http11/ext_help.h +0 -0
- data/ext/puma_http11/extconf.rb +11 -8
- data/ext/puma_http11/http11_parser.c +1 -1
- data/ext/puma_http11/http11_parser.h +1 -1
- data/ext/puma_http11/http11_parser.java.rl +2 -2
- data/ext/puma_http11/http11_parser.rl +2 -2
- data/ext/puma_http11/http11_parser_common.rl +2 -2
- data/ext/puma_http11/mini_ssl.c +36 -15
- data/ext/puma_http11/no_ssl/PumaHttp11Service.java +0 -0
- data/ext/puma_http11/org/jruby/puma/Http11.java +3 -5
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +1 -1
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +156 -53
- data/ext/puma_http11/puma_http11.c +17 -9
- data/lib/puma/app/status.rb +3 -3
- data/lib/puma/binder.rb +36 -42
- data/lib/puma/cli.rb +11 -17
- data/lib/puma/client.rb +29 -53
- data/lib/puma/cluster/worker.rb +13 -11
- data/lib/puma/cluster/worker_handle.rb +4 -1
- data/lib/puma/cluster.rb +28 -25
- data/lib/puma/commonlogger.rb +0 -0
- data/lib/puma/configuration.rb +74 -58
- data/lib/puma/const.rb +14 -26
- data/lib/puma/control_cli.rb +3 -6
- data/lib/puma/detect.rb +2 -0
- data/lib/puma/dsl.rb +93 -52
- data/lib/puma/error_logger.rb +17 -9
- data/lib/puma/events.rb +6 -126
- data/lib/puma/io_buffer.rb +29 -4
- data/lib/puma/jruby_restart.rb +2 -1
- data/lib/puma/json_serialization.rb +0 -0
- data/lib/puma/launcher/bundle_pruner.rb +104 -0
- data/lib/puma/launcher.rb +96 -156
- data/lib/puma/log_writer.rb +137 -0
- data/lib/puma/minissl/context_builder.rb +23 -12
- data/lib/puma/minissl.rb +82 -11
- data/lib/puma/null_io.rb +0 -0
- data/lib/puma/plugin/tmp_restart.rb +1 -1
- data/lib/puma/plugin.rb +0 -0
- data/lib/puma/puma_http11.jar +0 -0
- data/lib/puma/rack/builder.rb +4 -4
- data/lib/puma/rack/urlmap.rb +0 -0
- data/lib/puma/rack_default.rb +1 -1
- data/lib/puma/reactor.rb +3 -3
- data/lib/puma/request.rb +295 -177
- data/lib/puma/runner.rb +41 -20
- data/lib/puma/server.rb +53 -66
- data/lib/puma/single.rb +10 -10
- data/lib/puma/state_file.rb +1 -4
- data/lib/puma/systemd.rb +3 -2
- data/lib/puma/thread_pool.rb +16 -13
- data/lib/puma/util.rb +0 -11
- data/lib/puma.rb +10 -9
- data/lib/rack/handler/puma.rb +9 -9
- data/tools/Dockerfile +0 -0
- data/tools/trickletest.rb +0 -0
- metadata +10 -7
- data/lib/puma/queue_close.rb +0 -26
- data/lib/rack/version_restriction.rb +0 -15
data/lib/puma/launcher.rb
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
3
|
+
require_relative 'log_writer'
|
4
|
+
require_relative 'events'
|
5
|
+
require_relative 'detect'
|
6
|
+
require_relative 'cluster'
|
7
|
+
require_relative 'single'
|
8
|
+
require_relative 'const'
|
9
|
+
require_relative 'binder'
|
9
10
|
|
10
11
|
module Puma
|
11
12
|
# Puma::Launcher is the single entry point for starting a Puma server based on user
|
@@ -15,18 +16,14 @@ module Puma
|
|
15
16
|
# It is responsible for either launching a cluster of Puma workers or a single
|
16
17
|
# puma server.
|
17
18
|
class Launcher
|
18
|
-
|
19
|
-
|
20
|
-
:logger, :lowlevel_error_handler,
|
21
|
-
:before_worker_shutdown, :before_worker_boot, :before_worker_fork,
|
22
|
-
:after_worker_boot, :before_fork, :on_restart
|
23
|
-
]
|
19
|
+
autoload :BundlePruner, 'puma/launcher/bundle_pruner'
|
20
|
+
|
24
21
|
# Returns an instance of Launcher
|
25
22
|
#
|
26
23
|
# +conf+ A Puma::Configuration object indicating how to run the server.
|
27
24
|
#
|
28
25
|
# +launcher_args+ A Hash that currently has one required key `:events`,
|
29
|
-
# this is expected to hold an object similar to an `Puma::
|
26
|
+
# this is expected to hold an object similar to an `Puma::LogWriter.stdio`,
|
30
27
|
# this object will be responsible for broadcasting Puma's internal state
|
31
28
|
# to a logging destination. An optional key `:argv` can be supplied,
|
32
29
|
# this should be an array of strings, these arguments are re-used when
|
@@ -40,25 +37,28 @@ module Puma
|
|
40
37
|
# [200, {}, ["hello world"]]
|
41
38
|
# end
|
42
39
|
# end
|
43
|
-
# Puma::Launcher.new(conf,
|
40
|
+
# Puma::Launcher.new(conf, log_writer: Puma::LogWriter.stdio).run
|
44
41
|
def initialize(conf, launcher_args={})
|
45
42
|
@runner = nil
|
46
|
-
@
|
43
|
+
@log_writer = launcher_args[:log_writer] || LogWriter::DEFAULT
|
44
|
+
@events = launcher_args[:events] || Events.new
|
47
45
|
@argv = launcher_args[:argv] || []
|
48
46
|
@original_argv = @argv.dup
|
49
47
|
@config = conf
|
50
48
|
|
51
|
-
@
|
52
|
-
@binder.create_inherited_fds(ENV).each { |k| ENV.delete k }
|
53
|
-
@binder.create_activated_fds(ENV).each { |k| ENV.delete k }
|
54
|
-
|
55
|
-
@environment = conf.environment
|
49
|
+
@config.options[:log_writer] = @log_writer
|
56
50
|
|
57
51
|
# Advertise the Configuration
|
58
52
|
Puma.cli_config = @config if defined?(Puma.cli_config)
|
59
53
|
|
60
54
|
@config.load
|
61
55
|
|
56
|
+
@binder = Binder.new(@log_writer, conf)
|
57
|
+
@binder.create_inherited_fds(ENV).each { |k| ENV.delete k }
|
58
|
+
@binder.create_activated_fds(ENV).each { |k| ENV.delete k }
|
59
|
+
|
60
|
+
@environment = conf.environment
|
61
|
+
|
62
62
|
if @config.options[:bind_to_activated_sockets]
|
63
63
|
@config.options[:binds] = @binder.synthesize_binds_from_activated_fs(
|
64
64
|
@config.options[:binds],
|
@@ -69,8 +69,8 @@ module Puma
|
|
69
69
|
@options = @config.options
|
70
70
|
@config.clamp
|
71
71
|
|
72
|
-
@
|
73
|
-
@
|
72
|
+
@log_writer.formatter = LogWriter::PidFormatter.new if clustered?
|
73
|
+
@log_writer.formatter = options[:log_formatter] if @options[:log_formatter]
|
74
74
|
|
75
75
|
generate_restart_data
|
76
76
|
|
@@ -80,17 +80,17 @@ module Puma
|
|
80
80
|
|
81
81
|
Dir.chdir(@restart_dir)
|
82
82
|
|
83
|
-
prune_bundler
|
83
|
+
prune_bundler!
|
84
84
|
|
85
85
|
@environment = @options[:environment] if @options[:environment]
|
86
86
|
set_rack_environment
|
87
87
|
|
88
88
|
if clustered?
|
89
|
-
@options[:logger] = @
|
89
|
+
@options[:logger] = @log_writer
|
90
90
|
|
91
|
-
@runner = Cluster.new(self
|
91
|
+
@runner = Cluster.new(self)
|
92
92
|
else
|
93
|
-
@runner = Single.new(self
|
93
|
+
@runner = Single.new(self)
|
94
94
|
end
|
95
95
|
Puma.stats_object = @runner
|
96
96
|
|
@@ -99,7 +99,7 @@ module Puma
|
|
99
99
|
log_config if ENV['PUMA_LOG_CONFIG']
|
100
100
|
end
|
101
101
|
|
102
|
-
attr_reader :binder, :events, :config, :options, :restart_dir
|
102
|
+
attr_reader :binder, :log_writer, :events, :config, :options, :restart_dir
|
103
103
|
|
104
104
|
# Return stats about the server
|
105
105
|
def stats
|
@@ -115,7 +115,7 @@ module Puma
|
|
115
115
|
permission = @options[:state_permission]
|
116
116
|
return unless path
|
117
117
|
|
118
|
-
|
118
|
+
require_relative 'state_file'
|
119
119
|
|
120
120
|
sf = StateFile.new
|
121
121
|
sf.pid = Process.pid
|
@@ -172,16 +172,7 @@ module Puma
|
|
172
172
|
|
173
173
|
# Run the server. This blocks until the server is stopped
|
174
174
|
def run
|
175
|
-
previous_env =
|
176
|
-
if defined?(Bundler)
|
177
|
-
env = Bundler::ORIGINAL_ENV.dup
|
178
|
-
# add -rbundler/setup so we load from Gemfile when restarting
|
179
|
-
bundle = "-rbundler/setup"
|
180
|
-
env["RUBYOPT"] = [env["RUBYOPT"], bundle].join(" ").lstrip unless env["RUBYOPT"].to_s.include?(bundle)
|
181
|
-
env
|
182
|
-
else
|
183
|
-
ENV.to_h
|
184
|
-
end
|
175
|
+
previous_env = get_env
|
185
176
|
|
186
177
|
@config.clamp
|
187
178
|
|
@@ -190,23 +181,11 @@ module Puma
|
|
190
181
|
setup_signals
|
191
182
|
set_process_title
|
192
183
|
integrate_with_systemd
|
184
|
+
|
185
|
+
# This blocks until the server is stopped
|
193
186
|
@runner.run
|
194
187
|
|
195
|
-
|
196
|
-
when :halt
|
197
|
-
log "* Stopping immediately!"
|
198
|
-
@runner.stop_control
|
199
|
-
when :run, :stop
|
200
|
-
graceful_stop
|
201
|
-
when :restart
|
202
|
-
log "* Restarting..."
|
203
|
-
ENV.replace(previous_env)
|
204
|
-
@runner.stop_control
|
205
|
-
restart!
|
206
|
-
when :exit
|
207
|
-
# nothing
|
208
|
-
end
|
209
|
-
close_binder_listeners unless @status == :restart
|
188
|
+
do_run_finished(previous_env)
|
210
189
|
end
|
211
190
|
|
212
191
|
# Return all tcp ports the launcher may be using, TCP or SSL
|
@@ -250,30 +229,56 @@ module Puma
|
|
250
229
|
|
251
230
|
private
|
252
231
|
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
232
|
+
def get_env
|
233
|
+
if defined?(Bundler)
|
234
|
+
env = Bundler::ORIGINAL_ENV.dup
|
235
|
+
# add -rbundler/setup so we load from Gemfile when restarting
|
236
|
+
bundle = "-rbundler/setup"
|
237
|
+
env["RUBYOPT"] = [env["RUBYOPT"], bundle].join(" ").lstrip unless env["RUBYOPT"].to_s.include?(bundle)
|
238
|
+
env
|
239
|
+
else
|
240
|
+
ENV.to_h
|
262
241
|
end
|
263
242
|
end
|
264
243
|
|
265
|
-
def
|
266
|
-
|
244
|
+
def do_run_finished(previous_env)
|
245
|
+
case @status
|
246
|
+
when :halt
|
247
|
+
do_forceful_stop
|
248
|
+
when :run, :stop
|
249
|
+
do_graceful_stop
|
250
|
+
when :restart
|
251
|
+
do_restart(previous_env)
|
252
|
+
end
|
253
|
+
|
254
|
+
close_binder_listeners unless @status == :restart
|
255
|
+
end
|
256
|
+
|
257
|
+
def do_forceful_stop
|
258
|
+
log "* Stopping immediately!"
|
259
|
+
@runner.stop_control
|
260
|
+
end
|
261
|
+
|
262
|
+
def do_graceful_stop
|
263
|
+
@events.fire_on_stopped!
|
264
|
+
@runner.stop_blocked
|
265
|
+
end
|
266
|
+
|
267
|
+
def do_restart(previous_env)
|
268
|
+
log "* Restarting..."
|
269
|
+
ENV.replace(previous_env)
|
270
|
+
@runner.stop_control
|
271
|
+
restart!
|
267
272
|
end
|
268
273
|
|
269
274
|
def restart!
|
270
275
|
@events.fire_on_restart!
|
271
|
-
@config.run_hooks :on_restart, self, @
|
276
|
+
@config.run_hooks :on_restart, self, @log_writer
|
272
277
|
|
273
278
|
if Puma.jruby?
|
274
279
|
close_binder_listeners
|
275
280
|
|
276
|
-
|
281
|
+
require_relative 'jruby_restart'
|
277
282
|
JRubyRestart.chdir_exec(@restart_dir, restart_args)
|
278
283
|
elsif Puma.windows?
|
279
284
|
close_binder_listeners
|
@@ -290,72 +295,31 @@ module Puma
|
|
290
295
|
end
|
291
296
|
end
|
292
297
|
|
293
|
-
#
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
Array(@options[:extra_runtime_dependencies]).map do |d_name|
|
303
|
-
if (spec = spec_for_gem(d_name))
|
304
|
-
require_paths_for_gem(spec)
|
305
|
-
else
|
306
|
-
log "* Could not load extra dependency: #{d_name}"
|
307
|
-
nil
|
308
|
-
end
|
309
|
-
end.flatten.compact
|
310
|
-
end
|
311
|
-
|
312
|
-
# @!attribute [r] puma_wild_location
|
313
|
-
def puma_wild_location
|
314
|
-
puma = spec_for_gem("puma")
|
315
|
-
dirs = require_paths_for_gem(puma)
|
316
|
-
puma_lib_dir = dirs.detect { |x| File.exist? File.join(x, '../bin/puma-wild') }
|
317
|
-
File.expand_path(File.join(puma_lib_dir, "../bin/puma-wild"))
|
318
|
-
end
|
319
|
-
|
320
|
-
def prune_bundler
|
321
|
-
return if ENV['PUMA_BUNDLER_PRUNED']
|
322
|
-
return unless defined?(Bundler)
|
323
|
-
require_rubygems_min_version!(Gem::Version.new("2.2"), "prune_bundler")
|
324
|
-
unless puma_wild_location
|
325
|
-
log "! Unable to prune Bundler environment, continuing"
|
326
|
-
return
|
298
|
+
# If configured, write the pid of the current process out
|
299
|
+
# to a file.
|
300
|
+
def write_pid
|
301
|
+
path = @options[:pidfile]
|
302
|
+
return unless path
|
303
|
+
cur_pid = Process.pid
|
304
|
+
File.write path, cur_pid, mode: 'wb:UTF-8'
|
305
|
+
at_exit do
|
306
|
+
delete_pidfile if cur_pid == Process.pid
|
327
307
|
end
|
308
|
+
end
|
328
309
|
|
329
|
-
|
330
|
-
|
331
|
-
log '* Pruning Bundler environment'
|
332
|
-
home = ENV['GEM_HOME']
|
333
|
-
bundle_gemfile = Bundler.original_env['BUNDLE_GEMFILE']
|
334
|
-
bundle_app_config = Bundler.original_env['BUNDLE_APP_CONFIG']
|
335
|
-
with_unbundled_env do
|
336
|
-
ENV['GEM_HOME'] = home
|
337
|
-
ENV['BUNDLE_GEMFILE'] = bundle_gemfile
|
338
|
-
ENV['PUMA_BUNDLER_PRUNED'] = '1'
|
339
|
-
ENV["BUNDLE_APP_CONFIG"] = bundle_app_config
|
340
|
-
args = [Gem.ruby, puma_wild_location, '-I', dirs.join(':')] + @original_argv
|
341
|
-
# Ruby 2.0+ defaults to true which breaks socket activation
|
342
|
-
args += [{:close_others => false}]
|
343
|
-
Kernel.exec(*args)
|
344
|
-
end
|
310
|
+
def reload_worker_directory
|
311
|
+
@runner.reload_worker_directory if @runner.respond_to?(:reload_worker_directory)
|
345
312
|
end
|
346
313
|
|
347
|
-
#
|
348
314
|
# Puma's systemd integration allows Puma to inform systemd:
|
349
315
|
# 1. when it has successfully started
|
350
316
|
# 2. when it is starting shutdown
|
351
317
|
# 3. periodically for a liveness check with a watchdog thread
|
352
|
-
#
|
353
|
-
|
354
318
|
def integrate_with_systemd
|
355
319
|
return unless ENV["NOTIFY_SOCKET"]
|
356
320
|
|
357
321
|
begin
|
358
|
-
|
322
|
+
require_relative 'systemd'
|
359
323
|
rescue LoadError
|
360
324
|
log "Systemd integration failed. It looks like you're trying to use systemd notify but don't have sd_notify gem installed"
|
361
325
|
return
|
@@ -363,21 +327,13 @@ module Puma
|
|
363
327
|
|
364
328
|
log "* Enabling systemd notification integration"
|
365
329
|
|
366
|
-
systemd = Systemd.new(@events)
|
330
|
+
systemd = Systemd.new(@log_writer, @events)
|
367
331
|
systemd.hook_events
|
368
332
|
systemd.start_watchdog
|
369
333
|
end
|
370
334
|
|
371
|
-
def spec_for_gem(gem_name)
|
372
|
-
Bundler.rubygems.loaded_specs(gem_name)
|
373
|
-
end
|
374
|
-
|
375
|
-
def require_paths_for_gem(gem_spec)
|
376
|
-
gem_spec.full_require_paths
|
377
|
-
end
|
378
|
-
|
379
335
|
def log(str)
|
380
|
-
@
|
336
|
+
@log_writer.log(str)
|
381
337
|
end
|
382
338
|
|
383
339
|
def clustered?
|
@@ -385,15 +341,10 @@ module Puma
|
|
385
341
|
end
|
386
342
|
|
387
343
|
def unsupported(str)
|
388
|
-
@
|
344
|
+
@log_writer.error(str)
|
389
345
|
raise UnsupportedOption
|
390
346
|
end
|
391
347
|
|
392
|
-
def graceful_stop
|
393
|
-
@events.fire_on_stopped!
|
394
|
-
@runner.stop_blocked
|
395
|
-
end
|
396
|
-
|
397
348
|
def set_process_title
|
398
349
|
Process.respond_to?(:setproctitle) ? Process.setproctitle(title) : $0 = title
|
399
350
|
end
|
@@ -419,6 +370,11 @@ module Puma
|
|
419
370
|
@options[:prune_bundler] && clustered? && !@options[:preload_app]
|
420
371
|
end
|
421
372
|
|
373
|
+
def prune_bundler!
|
374
|
+
return unless prune_bundler?
|
375
|
+
BundlePruner.new(@original_argv, @options[:extra_runtime_dependencies], @log_writer).prune
|
376
|
+
end
|
377
|
+
|
422
378
|
def generate_restart_data
|
423
379
|
if dir = @options[:directory]
|
424
380
|
@restart_dir = dir
|
@@ -485,7 +441,8 @@ module Puma
|
|
485
441
|
|
486
442
|
begin
|
487
443
|
Signal.trap "SIGTERM" do
|
488
|
-
|
444
|
+
# Shortcut the control flow in case raise_exception_on_sigterm is true
|
445
|
+
do_graceful_stop
|
489
446
|
|
490
447
|
raise(SignalException, "SIGTERM") if @options[:raise_exception_on_sigterm]
|
491
448
|
end
|
@@ -517,8 +474,8 @@ module Puma
|
|
517
474
|
unless Puma.jruby? # INFO in use by JVM already
|
518
475
|
Signal.trap "SIGINFO" do
|
519
476
|
thread_status do |name, backtrace|
|
520
|
-
@
|
521
|
-
@
|
477
|
+
@log_writer.log(name)
|
478
|
+
@log_writer.log(backtrace.map { |bt| " #{bt}" })
|
522
479
|
end
|
523
480
|
end
|
524
481
|
end
|
@@ -528,23 +485,6 @@ module Puma
|
|
528
485
|
end
|
529
486
|
end
|
530
487
|
|
531
|
-
def require_rubygems_min_version!(min_version, feature)
|
532
|
-
return if min_version <= Gem::Version.new(Gem::VERSION)
|
533
|
-
|
534
|
-
raise "#{feature} is not supported on your version of RubyGems. " \
|
535
|
-
"You must have RubyGems #{min_version}+ to use this feature."
|
536
|
-
end
|
537
|
-
|
538
|
-
# @version 5.0.0
|
539
|
-
def with_unbundled_env
|
540
|
-
bundler_ver = Gem::Version.new(Bundler::VERSION)
|
541
|
-
if bundler_ver < Gem::Version.new('2.1.0')
|
542
|
-
Bundler.with_clean_env { yield }
|
543
|
-
else
|
544
|
-
Bundler.with_unbundled_env { yield }
|
545
|
-
end
|
546
|
-
end
|
547
|
-
|
548
488
|
def log_config
|
549
489
|
log "Configuration:"
|
550
490
|
|
@@ -0,0 +1,137 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'null_io'
|
4
|
+
require_relative 'error_logger'
|
5
|
+
require 'stringio'
|
6
|
+
require 'io/wait' unless Puma::HAS_NATIVE_IO_WAIT
|
7
|
+
|
8
|
+
module Puma
|
9
|
+
|
10
|
+
# Handles logging concerns for both standard messages
|
11
|
+
# (+stdout+) and errors (+stderr+).
|
12
|
+
class LogWriter
|
13
|
+
|
14
|
+
class DefaultFormatter
|
15
|
+
def call(str)
|
16
|
+
str
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class PidFormatter
|
21
|
+
def call(str)
|
22
|
+
"[#{$$}] #{str}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
LOG_QUEUE = Queue.new
|
27
|
+
|
28
|
+
attr_reader :stdout,
|
29
|
+
:stderr
|
30
|
+
|
31
|
+
attr_accessor :formatter
|
32
|
+
|
33
|
+
# Create a LogWriter that prints to +stdout+ and +stderr+.
|
34
|
+
def initialize(stdout, stderr)
|
35
|
+
@formatter = DefaultFormatter.new
|
36
|
+
@stdout = stdout
|
37
|
+
@stderr = stderr
|
38
|
+
|
39
|
+
@debug = ENV.key?('PUMA_DEBUG')
|
40
|
+
@error_logger = ErrorLogger.new(@stderr)
|
41
|
+
end
|
42
|
+
|
43
|
+
DEFAULT = new(STDOUT, STDERR)
|
44
|
+
|
45
|
+
# Returns an LogWriter object which writes its status to
|
46
|
+
# two StringIO objects.
|
47
|
+
def self.strings
|
48
|
+
LogWriter.new(StringIO.new, StringIO.new)
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.stdio
|
52
|
+
LogWriter.new($stdout, $stderr)
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.null
|
56
|
+
n = NullIO.new
|
57
|
+
LogWriter.new(n, n)
|
58
|
+
end
|
59
|
+
|
60
|
+
# Write +str+ to +@stdout+
|
61
|
+
def log(str)
|
62
|
+
internal_write "#{@formatter.call str}\n"
|
63
|
+
end
|
64
|
+
|
65
|
+
def write(str)
|
66
|
+
internal_write @formatter.call(str)
|
67
|
+
end
|
68
|
+
|
69
|
+
def internal_write(str)
|
70
|
+
LOG_QUEUE << str
|
71
|
+
while (w_str = LOG_QUEUE.pop(true)) do
|
72
|
+
begin
|
73
|
+
@stdout.is_a?(IO) and @stdout.wait_writable(1)
|
74
|
+
@stdout.write w_str
|
75
|
+
@stdout.flush unless @stdout.sync
|
76
|
+
rescue Errno::EPIPE, Errno::EBADF, IOError
|
77
|
+
end
|
78
|
+
end
|
79
|
+
rescue ThreadError
|
80
|
+
end
|
81
|
+
private :internal_write
|
82
|
+
|
83
|
+
def debug(str)
|
84
|
+
log("% #{str}") if @debug
|
85
|
+
end
|
86
|
+
|
87
|
+
# Write +str+ to +@stderr+
|
88
|
+
def error(str)
|
89
|
+
@error_logger.info(text: @formatter.call("ERROR: #{str}"))
|
90
|
+
exit 1
|
91
|
+
end
|
92
|
+
|
93
|
+
def format(str)
|
94
|
+
formatter.call(str)
|
95
|
+
end
|
96
|
+
|
97
|
+
# An HTTP connection error has occurred.
|
98
|
+
# +error+ a connection exception, +req+ the request,
|
99
|
+
# and +text+ additional info
|
100
|
+
# @version 5.0.0
|
101
|
+
def connection_error(error, req, text="HTTP connection error")
|
102
|
+
@error_logger.info(error: error, req: req, text: text)
|
103
|
+
end
|
104
|
+
|
105
|
+
# An HTTP parse error has occurred.
|
106
|
+
# +error+ a parsing exception,
|
107
|
+
# and +req+ the request.
|
108
|
+
def parse_error(error, req)
|
109
|
+
@error_logger.info(error: error, req: req, text: 'HTTP parse error, malformed request')
|
110
|
+
end
|
111
|
+
|
112
|
+
# An SSL error has occurred.
|
113
|
+
# @param error <Puma::MiniSSL::SSLError>
|
114
|
+
# @param ssl_socket <Puma::MiniSSL::Socket>
|
115
|
+
def ssl_error(error, ssl_socket)
|
116
|
+
peeraddr = ssl_socket.peeraddr.last rescue "<unknown>"
|
117
|
+
peercert = ssl_socket.peercert
|
118
|
+
subject = peercert ? peercert.subject : nil
|
119
|
+
@error_logger.info(error: error, text: "SSL error, peer: #{peeraddr}, peer cert: #{subject}")
|
120
|
+
end
|
121
|
+
|
122
|
+
# An unknown error has occurred.
|
123
|
+
# +error+ an exception object, +req+ the request,
|
124
|
+
# and +text+ additional info
|
125
|
+
def unknown_error(error, req=nil, text="Unknown error")
|
126
|
+
@error_logger.info(error: error, req: req, text: text)
|
127
|
+
end
|
128
|
+
|
129
|
+
# Log occurred error debug dump.
|
130
|
+
# +error+ an exception object, +req+ the request,
|
131
|
+
# and +text+ additional info
|
132
|
+
# @version 5.0.0
|
133
|
+
def debug_error(error, req=nil, text="")
|
134
|
+
@error_logger.debug(error: error, req: req, text: text)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
module Puma
|
2
2
|
module MiniSSL
|
3
3
|
class ContextBuilder
|
4
|
-
def initialize(params,
|
4
|
+
def initialize(params, log_writer)
|
5
5
|
@params = params
|
6
|
-
@
|
6
|
+
@log_writer = log_writer
|
7
7
|
end
|
8
8
|
|
9
9
|
def context
|
@@ -11,27 +11,36 @@ module Puma
|
|
11
11
|
|
12
12
|
if defined?(JRUBY_VERSION)
|
13
13
|
unless params['keystore']
|
14
|
-
|
14
|
+
log_writer.error "Please specify the Java keystore via 'keystore='"
|
15
15
|
end
|
16
16
|
|
17
17
|
ctx.keystore = params['keystore']
|
18
18
|
|
19
19
|
unless params['keystore-pass']
|
20
|
-
|
20
|
+
log_writer.error "Please specify the Java keystore password via 'keystore-pass='"
|
21
21
|
end
|
22
22
|
|
23
23
|
ctx.keystore_pass = params['keystore-pass']
|
24
|
-
ctx.
|
24
|
+
ctx.keystore_type = params['keystore-type']
|
25
|
+
|
26
|
+
if truststore = params['truststore']
|
27
|
+
ctx.truststore = truststore.eql?('default') ? :default : truststore
|
28
|
+
ctx.truststore_pass = params['truststore-pass']
|
29
|
+
ctx.truststore_type = params['truststore-type']
|
30
|
+
end
|
31
|
+
|
32
|
+
ctx.cipher_suites = params['cipher_suites'] || params['ssl_cipher_list']
|
33
|
+
ctx.protocols = params['protocols'] if params['protocols']
|
25
34
|
else
|
26
35
|
if params['key'].nil? && params['key_pem'].nil?
|
27
|
-
|
36
|
+
log_writer.error "Please specify the SSL key via 'key=' or 'key_pem='"
|
28
37
|
end
|
29
38
|
|
30
39
|
ctx.key = params['key'] if params['key']
|
31
40
|
ctx.key_pem = params['key_pem'] if params['key_pem']
|
32
41
|
|
33
42
|
if params['cert'].nil? && params['cert_pem'].nil?
|
34
|
-
|
43
|
+
log_writer.error "Please specify the SSL cert via 'cert=' or 'cert_pem='"
|
35
44
|
end
|
36
45
|
|
37
46
|
ctx.cert = params['cert'] if params['cert']
|
@@ -39,16 +48,18 @@ module Puma
|
|
39
48
|
|
40
49
|
if ['peer', 'force_peer'].include?(params['verify_mode'])
|
41
50
|
unless params['ca']
|
42
|
-
|
51
|
+
log_writer.error "Please specify the SSL ca via 'ca='"
|
43
52
|
end
|
44
53
|
end
|
45
54
|
|
46
55
|
ctx.ca = params['ca'] if params['ca']
|
47
56
|
ctx.ssl_cipher_filter = params['ssl_cipher_filter'] if params['ssl_cipher_filter']
|
57
|
+
|
58
|
+
ctx.reuse = params['reuse'] if params['reuse']
|
48
59
|
end
|
49
60
|
|
50
|
-
ctx.no_tlsv1
|
51
|
-
ctx.no_tlsv1_1 =
|
61
|
+
ctx.no_tlsv1 = params['no_tlsv1'] == 'true'
|
62
|
+
ctx.no_tlsv1_1 = params['no_tlsv1_1'] == 'true'
|
52
63
|
|
53
64
|
if params['verify_mode']
|
54
65
|
ctx.verify_mode = case params['verify_mode']
|
@@ -59,7 +70,7 @@ module Puma
|
|
59
70
|
when "none"
|
60
71
|
MiniSSL::VERIFY_NONE
|
61
72
|
else
|
62
|
-
|
73
|
+
log_writer.error "Please specify a valid verify_mode="
|
63
74
|
MiniSSL::VERIFY_NONE
|
64
75
|
end
|
65
76
|
end
|
@@ -75,7 +86,7 @@ module Puma
|
|
75
86
|
|
76
87
|
private
|
77
88
|
|
78
|
-
attr_reader :params, :
|
89
|
+
attr_reader :params, :log_writer
|
79
90
|
end
|
80
91
|
end
|
81
92
|
end
|