puma 5.6.9 → 6.0.0

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.

Files changed (84) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +96 -28
  3. data/LICENSE +0 -0
  4. data/README.md +21 -17
  5. data/bin/puma-wild +1 -1
  6. data/docs/architecture.md +0 -0
  7. data/docs/compile_options.md +34 -0
  8. data/docs/deployment.md +0 -0
  9. data/docs/fork_worker.md +1 -3
  10. data/docs/images/puma-connection-flow-no-reactor.png +0 -0
  11. data/docs/images/puma-connection-flow.png +0 -0
  12. data/docs/images/puma-general-arch.png +0 -0
  13. data/docs/jungle/README.md +0 -0
  14. data/docs/jungle/rc.d/README.md +0 -0
  15. data/docs/jungle/rc.d/puma.conf +0 -0
  16. data/docs/kubernetes.md +0 -0
  17. data/docs/nginx.md +0 -0
  18. data/docs/plugins.md +0 -0
  19. data/docs/rails_dev_mode.md +0 -0
  20. data/docs/restart.md +0 -0
  21. data/docs/signals.md +0 -0
  22. data/docs/stats.md +0 -0
  23. data/docs/systemd.md +0 -0
  24. data/docs/testing_benchmarks_local_files.md +150 -0
  25. data/docs/testing_test_rackup_ci_files.md +36 -0
  26. data/ext/puma_http11/PumaHttp11Service.java +0 -0
  27. data/ext/puma_http11/ext_help.h +0 -0
  28. data/ext/puma_http11/extconf.rb +11 -8
  29. data/ext/puma_http11/http11_parser.c +1 -1
  30. data/ext/puma_http11/http11_parser.h +1 -1
  31. data/ext/puma_http11/http11_parser.java.rl +2 -2
  32. data/ext/puma_http11/http11_parser.rl +2 -2
  33. data/ext/puma_http11/http11_parser_common.rl +2 -2
  34. data/ext/puma_http11/mini_ssl.c +36 -15
  35. data/ext/puma_http11/no_ssl/PumaHttp11Service.java +0 -0
  36. data/ext/puma_http11/org/jruby/puma/Http11.java +3 -5
  37. data/ext/puma_http11/org/jruby/puma/Http11Parser.java +1 -1
  38. data/ext/puma_http11/org/jruby/puma/MiniSSL.java +156 -53
  39. data/ext/puma_http11/puma_http11.c +17 -9
  40. data/lib/puma/app/status.rb +3 -3
  41. data/lib/puma/binder.rb +36 -42
  42. data/lib/puma/cli.rb +11 -17
  43. data/lib/puma/client.rb +29 -53
  44. data/lib/puma/cluster/worker.rb +13 -11
  45. data/lib/puma/cluster/worker_handle.rb +4 -1
  46. data/lib/puma/cluster.rb +28 -25
  47. data/lib/puma/commonlogger.rb +0 -0
  48. data/lib/puma/configuration.rb +74 -58
  49. data/lib/puma/const.rb +14 -26
  50. data/lib/puma/control_cli.rb +3 -6
  51. data/lib/puma/detect.rb +2 -0
  52. data/lib/puma/dsl.rb +93 -52
  53. data/lib/puma/error_logger.rb +17 -9
  54. data/lib/puma/events.rb +6 -126
  55. data/lib/puma/io_buffer.rb +29 -4
  56. data/lib/puma/jruby_restart.rb +2 -1
  57. data/lib/puma/json_serialization.rb +0 -0
  58. data/lib/puma/launcher/bundle_pruner.rb +104 -0
  59. data/lib/puma/launcher.rb +96 -156
  60. data/lib/puma/log_writer.rb +137 -0
  61. data/lib/puma/minissl/context_builder.rb +23 -12
  62. data/lib/puma/minissl.rb +82 -11
  63. data/lib/puma/null_io.rb +0 -0
  64. data/lib/puma/plugin/tmp_restart.rb +1 -1
  65. data/lib/puma/plugin.rb +0 -0
  66. data/lib/puma/rack/builder.rb +4 -4
  67. data/lib/puma/rack/urlmap.rb +0 -0
  68. data/lib/puma/rack_default.rb +1 -1
  69. data/lib/puma/reactor.rb +3 -3
  70. data/lib/puma/request.rb +295 -177
  71. data/lib/puma/runner.rb +41 -20
  72. data/lib/puma/server.rb +53 -66
  73. data/lib/puma/single.rb +10 -10
  74. data/lib/puma/state_file.rb +1 -4
  75. data/lib/puma/systemd.rb +3 -2
  76. data/lib/puma/thread_pool.rb +16 -13
  77. data/lib/puma/util.rb +0 -11
  78. data/lib/puma.rb +10 -9
  79. data/lib/rack/handler/puma.rb +9 -9
  80. data/tools/Dockerfile +0 -0
  81. data/tools/trickletest.rb +0 -0
  82. metadata +9 -6
  83. data/lib/puma/queue_close.rb +0 -26
  84. 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
- require 'puma/events'
4
- require 'puma/detect'
5
- require 'puma/cluster'
6
- require 'puma/single'
7
- require 'puma/const'
8
- require 'puma/binder'
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
- # @deprecated 6.0.0
19
- KEYS_NOT_TO_PERSIST_IN_STATE = [
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::Events.stdio`,
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, events: Puma::Events.stdio).run
40
+ # Puma::Launcher.new(conf, log_writer: Puma::LogWriter.stdio).run
44
41
  def initialize(conf, launcher_args={})
45
42
  @runner = nil
46
- @events = launcher_args[:events] || Events::DEFAULT
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
- @binder = Binder.new(@events, conf)
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
- @events.formatter = Events::PidFormatter.new if clustered?
73
- @events.formatter = options[:log_formatter] if @options[:log_formatter]
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 if 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] = @events
89
+ @options[:logger] = @log_writer
90
90
 
91
- @runner = Cluster.new(self, @events)
91
+ @runner = Cluster.new(self)
92
92
  else
93
- @runner = Single.new(self, @events)
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
- require 'puma/state_file'
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
- case @status
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
- # If configured, write the pid of the current process out
254
- # to a file.
255
- def write_pid
256
- path = @options[:pidfile]
257
- return unless path
258
- cur_pid = Process.pid
259
- File.write path, cur_pid, mode: 'wb:UTF-8'
260
- at_exit do
261
- delete_pidfile if cur_pid == Process.pid
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 reload_worker_directory
266
- @runner.reload_worker_directory if @runner.respond_to?(:reload_worker_directory)
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, @events
276
+ @config.run_hooks :on_restart, self, @log_writer
272
277
 
273
278
  if Puma.jruby?
274
279
  close_binder_listeners
275
280
 
276
- require 'puma/jruby_restart'
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
- # @!attribute [r] files_to_require_after_prune
294
- def files_to_require_after_prune
295
- puma = spec_for_gem("puma")
296
-
297
- require_paths_for_gem(puma) + extra_runtime_deps_directories
298
- end
299
-
300
- # @!attribute [r] extra_runtime_deps_directories
301
- def extra_runtime_deps_directories
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
- dirs = files_to_require_after_prune
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
- require 'puma/systemd'
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
- @events.log str
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
- @events.error(str)
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
- graceful_stop
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
- @events.log name
521
- @events.log backtrace.map { |bt| " #{bt}" }
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, events)
4
+ def initialize(params, log_writer)
5
5
  @params = params
6
- @events = events
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
- events.error "Please specify the Java keystore via 'keystore='"
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
- events.error "Please specify the Java keystore password via 'keystore-pass='"
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.ssl_cipher_list = params['ssl_cipher_list'] if params['ssl_cipher_list']
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
- events.error "Please specify the SSL key via 'key=' or 'key_pem='"
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
- events.error "Please specify the SSL cert via 'cert=' or 'cert_pem='"
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
- events.error "Please specify the SSL ca via 'ca='"
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 = true if params['no_tlsv1'] == 'true'
51
- ctx.no_tlsv1_1 = true if params['no_tlsv1_1'] == 'true'
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
- events.error "Please specify a valid verify_mode="
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, :events
89
+ attr_reader :params, :log_writer
79
90
  end
80
91
  end
81
92
  end