puma 5.6.4 → 6.0.1

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 (58) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +154 -3
  3. data/README.md +21 -17
  4. data/bin/puma-wild +1 -1
  5. data/docs/compile_options.md +34 -0
  6. data/docs/fork_worker.md +1 -3
  7. data/docs/nginx.md +1 -1
  8. data/docs/testing_benchmarks_local_files.md +150 -0
  9. data/docs/testing_test_rackup_ci_files.md +36 -0
  10. data/ext/puma_http11/extconf.rb +18 -10
  11. data/ext/puma_http11/http11_parser.c +1 -1
  12. data/ext/puma_http11/http11_parser.h +1 -1
  13. data/ext/puma_http11/http11_parser.java.rl +2 -2
  14. data/ext/puma_http11/http11_parser.rl +2 -2
  15. data/ext/puma_http11/http11_parser_common.rl +2 -2
  16. data/ext/puma_http11/mini_ssl.c +63 -24
  17. data/ext/puma_http11/org/jruby/puma/Http11.java +3 -3
  18. data/ext/puma_http11/org/jruby/puma/Http11Parser.java +1 -1
  19. data/ext/puma_http11/org/jruby/puma/MiniSSL.java +166 -65
  20. data/ext/puma_http11/puma_http11.c +17 -9
  21. data/lib/puma/app/status.rb +6 -3
  22. data/lib/puma/binder.rb +37 -43
  23. data/lib/puma/cli.rb +11 -17
  24. data/lib/puma/client.rb +26 -13
  25. data/lib/puma/cluster/worker.rb +13 -11
  26. data/lib/puma/cluster/worker_handle.rb +4 -1
  27. data/lib/puma/cluster.rb +28 -25
  28. data/lib/puma/configuration.rb +74 -58
  29. data/lib/puma/const.rb +14 -18
  30. data/lib/puma/control_cli.rb +21 -18
  31. data/lib/puma/detect.rb +2 -0
  32. data/lib/puma/dsl.rb +97 -49
  33. data/lib/puma/error_logger.rb +17 -9
  34. data/lib/puma/events.rb +6 -126
  35. data/lib/puma/io_buffer.rb +39 -4
  36. data/lib/puma/jruby_restart.rb +2 -1
  37. data/lib/puma/launcher/bundle_pruner.rb +104 -0
  38. data/lib/puma/launcher.rb +107 -156
  39. data/lib/puma/log_writer.rb +137 -0
  40. data/lib/puma/minissl/context_builder.rb +23 -12
  41. data/lib/puma/minissl.rb +91 -15
  42. data/lib/puma/null_io.rb +5 -0
  43. data/lib/puma/plugin/tmp_restart.rb +1 -1
  44. data/lib/puma/rack/builder.rb +4 -4
  45. data/lib/puma/rack_default.rb +1 -1
  46. data/lib/puma/reactor.rb +4 -4
  47. data/lib/puma/request.rb +334 -162
  48. data/lib/puma/runner.rb +41 -20
  49. data/lib/puma/server.rb +55 -69
  50. data/lib/puma/single.rb +10 -10
  51. data/lib/puma/state_file.rb +2 -4
  52. data/lib/puma/systemd.rb +3 -2
  53. data/lib/puma/thread_pool.rb +16 -16
  54. data/lib/puma/util.rb +12 -14
  55. data/lib/puma.rb +12 -9
  56. data/lib/rack/handler/puma.rb +9 -9
  57. metadata +7 -3
  58. data/lib/puma/queue_close.rb +0 -26
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
@@ -159,18 +159,20 @@ module Puma
159
159
  true
160
160
  end
161
161
 
162
+ # Begin a refork if supported
163
+ def refork
164
+ if clustered? && @runner.respond_to?(:fork_worker!) && @options[:fork_worker]
165
+ @runner.fork_worker!
166
+ true
167
+ else
168
+ log "* refork called but not available."
169
+ false
170
+ end
171
+ end
172
+
162
173
  # Run the server. This blocks until the server is stopped
163
174
  def run
164
- previous_env =
165
- if defined?(Bundler)
166
- env = Bundler::ORIGINAL_ENV.dup
167
- # add -rbundler/setup so we load from Gemfile when restarting
168
- bundle = "-rbundler/setup"
169
- env["RUBYOPT"] = [env["RUBYOPT"], bundle].join(" ").lstrip unless env["RUBYOPT"].to_s.include?(bundle)
170
- env
171
- else
172
- ENV.to_h
173
- end
175
+ previous_env = get_env
174
176
 
175
177
  @config.clamp
176
178
 
@@ -179,23 +181,11 @@ module Puma
179
181
  setup_signals
180
182
  set_process_title
181
183
  integrate_with_systemd
184
+
185
+ # This blocks until the server is stopped
182
186
  @runner.run
183
187
 
184
- case @status
185
- when :halt
186
- log "* Stopping immediately!"
187
- @runner.stop_control
188
- when :run, :stop
189
- graceful_stop
190
- when :restart
191
- log "* Restarting..."
192
- ENV.replace(previous_env)
193
- @runner.stop_control
194
- restart!
195
- when :exit
196
- # nothing
197
- end
198
- close_binder_listeners unless @status == :restart
188
+ do_run_finished(previous_env)
199
189
  end
200
190
 
201
191
  # Return all tcp ports the launcher may be using, TCP or SSL
@@ -239,30 +229,56 @@ module Puma
239
229
 
240
230
  private
241
231
 
242
- # If configured, write the pid of the current process out
243
- # to a file.
244
- def write_pid
245
- path = @options[:pidfile]
246
- return unless path
247
- cur_pid = Process.pid
248
- File.write path, cur_pid, mode: 'wb:UTF-8'
249
- at_exit do
250
- 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
251
241
  end
252
242
  end
253
243
 
254
- def reload_worker_directory
255
- @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!
256
272
  end
257
273
 
258
274
  def restart!
259
275
  @events.fire_on_restart!
260
- @config.run_hooks :on_restart, self, @events
276
+ @config.run_hooks :on_restart, self, @log_writer
261
277
 
262
278
  if Puma.jruby?
263
279
  close_binder_listeners
264
280
 
265
- require 'puma/jruby_restart'
281
+ require_relative 'jruby_restart'
266
282
  JRubyRestart.chdir_exec(@restart_dir, restart_args)
267
283
  elsif Puma.windows?
268
284
  close_binder_listeners
@@ -279,72 +295,31 @@ module Puma
279
295
  end
280
296
  end
281
297
 
282
- # @!attribute [r] files_to_require_after_prune
283
- def files_to_require_after_prune
284
- puma = spec_for_gem("puma")
285
-
286
- require_paths_for_gem(puma) + extra_runtime_deps_directories
287
- end
288
-
289
- # @!attribute [r] extra_runtime_deps_directories
290
- def extra_runtime_deps_directories
291
- Array(@options[:extra_runtime_dependencies]).map do |d_name|
292
- if (spec = spec_for_gem(d_name))
293
- require_paths_for_gem(spec)
294
- else
295
- log "* Could not load extra dependency: #{d_name}"
296
- nil
297
- end
298
- end.flatten.compact
299
- end
300
-
301
- # @!attribute [r] puma_wild_location
302
- def puma_wild_location
303
- puma = spec_for_gem("puma")
304
- dirs = require_paths_for_gem(puma)
305
- puma_lib_dir = dirs.detect { |x| File.exist? File.join(x, '../bin/puma-wild') }
306
- File.expand_path(File.join(puma_lib_dir, "../bin/puma-wild"))
307
- end
308
-
309
- def prune_bundler
310
- return if ENV['PUMA_BUNDLER_PRUNED']
311
- return unless defined?(Bundler)
312
- require_rubygems_min_version!(Gem::Version.new("2.2"), "prune_bundler")
313
- unless puma_wild_location
314
- log "! Unable to prune Bundler environment, continuing"
315
- 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
316
307
  end
308
+ end
317
309
 
318
- dirs = files_to_require_after_prune
319
-
320
- log '* Pruning Bundler environment'
321
- home = ENV['GEM_HOME']
322
- bundle_gemfile = Bundler.original_env['BUNDLE_GEMFILE']
323
- bundle_app_config = Bundler.original_env['BUNDLE_APP_CONFIG']
324
- with_unbundled_env do
325
- ENV['GEM_HOME'] = home
326
- ENV['BUNDLE_GEMFILE'] = bundle_gemfile
327
- ENV['PUMA_BUNDLER_PRUNED'] = '1'
328
- ENV["BUNDLE_APP_CONFIG"] = bundle_app_config
329
- args = [Gem.ruby, puma_wild_location, '-I', dirs.join(':')] + @original_argv
330
- # Ruby 2.0+ defaults to true which breaks socket activation
331
- args += [{:close_others => false}]
332
- Kernel.exec(*args)
333
- end
310
+ def reload_worker_directory
311
+ @runner.reload_worker_directory if @runner.respond_to?(:reload_worker_directory)
334
312
  end
335
313
 
336
- #
337
314
  # Puma's systemd integration allows Puma to inform systemd:
338
315
  # 1. when it has successfully started
339
316
  # 2. when it is starting shutdown
340
317
  # 3. periodically for a liveness check with a watchdog thread
341
- #
342
-
343
318
  def integrate_with_systemd
344
319
  return unless ENV["NOTIFY_SOCKET"]
345
320
 
346
321
  begin
347
- require 'puma/systemd'
322
+ require_relative 'systemd'
348
323
  rescue LoadError
349
324
  log "Systemd integration failed. It looks like you're trying to use systemd notify but don't have sd_notify gem installed"
350
325
  return
@@ -352,21 +327,13 @@ module Puma
352
327
 
353
328
  log "* Enabling systemd notification integration"
354
329
 
355
- systemd = Systemd.new(@events)
330
+ systemd = Systemd.new(@log_writer, @events)
356
331
  systemd.hook_events
357
332
  systemd.start_watchdog
358
333
  end
359
334
 
360
- def spec_for_gem(gem_name)
361
- Bundler.rubygems.loaded_specs(gem_name)
362
- end
363
-
364
- def require_paths_for_gem(gem_spec)
365
- gem_spec.full_require_paths
366
- end
367
-
368
335
  def log(str)
369
- @events.log str
336
+ @log_writer.log(str)
370
337
  end
371
338
 
372
339
  def clustered?
@@ -374,15 +341,10 @@ module Puma
374
341
  end
375
342
 
376
343
  def unsupported(str)
377
- @events.error(str)
344
+ @log_writer.error(str)
378
345
  raise UnsupportedOption
379
346
  end
380
347
 
381
- def graceful_stop
382
- @events.fire_on_stopped!
383
- @runner.stop_blocked
384
- end
385
-
386
348
  def set_process_title
387
349
  Process.respond_to?(:setproctitle) ? Process.setproctitle(title) : $0 = title
388
350
  end
@@ -408,6 +370,11 @@ module Puma
408
370
  @options[:prune_bundler] && clustered? && !@options[:preload_app]
409
371
  end
410
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
+
411
378
  def generate_restart_data
412
379
  if dir = @options[:directory]
413
380
  @restart_dir = dir
@@ -474,7 +441,8 @@ module Puma
474
441
 
475
442
  begin
476
443
  Signal.trap "SIGTERM" do
477
- graceful_stop
444
+ # Shortcut the control flow in case raise_exception_on_sigterm is true
445
+ do_graceful_stop
478
446
 
479
447
  raise(SignalException, "SIGTERM") if @options[:raise_exception_on_sigterm]
480
448
  end
@@ -506,8 +474,8 @@ module Puma
506
474
  unless Puma.jruby? # INFO in use by JVM already
507
475
  Signal.trap "SIGINFO" do
508
476
  thread_status do |name, backtrace|
509
- @events.log name
510
- @events.log backtrace.map { |bt| " #{bt}" }
477
+ @log_writer.log(name)
478
+ @log_writer.log(backtrace.map { |bt| " #{bt}" })
511
479
  end
512
480
  end
513
481
  end
@@ -517,23 +485,6 @@ module Puma
517
485
  end
518
486
  end
519
487
 
520
- def require_rubygems_min_version!(min_version, feature)
521
- return if min_version <= Gem::Version.new(Gem::VERSION)
522
-
523
- raise "#{feature} is not supported on your version of RubyGems. " \
524
- "You must have RubyGems #{min_version}+ to use this feature."
525
- end
526
-
527
- # @version 5.0.0
528
- def with_unbundled_env
529
- bundler_ver = Gem::Version.new(Bundler::VERSION)
530
- if bundler_ver < Gem::Version.new('2.1.0')
531
- Bundler.with_clean_env { yield }
532
- else
533
- Bundler.with_unbundled_env { yield }
534
- end
535
- end
536
-
537
488
  def log_config
538
489
  log "Configuration:"
539
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