puma 5.6.5 → 6.1.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 (60) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +165 -11
  3. data/README.md +22 -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/systemd.md +1 -2
  9. data/docs/testing_benchmarks_local_files.md +150 -0
  10. data/docs/testing_test_rackup_ci_files.md +36 -0
  11. data/ext/puma_http11/extconf.rb +11 -8
  12. data/ext/puma_http11/http11_parser.c +1 -1
  13. data/ext/puma_http11/http11_parser.h +1 -1
  14. data/ext/puma_http11/http11_parser.java.rl +2 -2
  15. data/ext/puma_http11/http11_parser.rl +2 -2
  16. data/ext/puma_http11/http11_parser_common.rl +2 -2
  17. data/ext/puma_http11/mini_ssl.c +36 -15
  18. data/ext/puma_http11/org/jruby/puma/Http11.java +3 -3
  19. data/ext/puma_http11/org/jruby/puma/Http11Parser.java +1 -1
  20. data/ext/puma_http11/org/jruby/puma/MiniSSL.java +156 -53
  21. data/ext/puma_http11/puma_http11.c +17 -9
  22. data/lib/puma/app/status.rb +3 -3
  23. data/lib/puma/binder.rb +40 -45
  24. data/lib/puma/cli.rb +11 -17
  25. data/lib/puma/client.rb +54 -16
  26. data/lib/puma/cluster/worker.rb +18 -11
  27. data/lib/puma/cluster/worker_handle.rb +4 -1
  28. data/lib/puma/cluster.rb +33 -30
  29. data/lib/puma/configuration.rb +75 -58
  30. data/lib/puma/const.rb +76 -88
  31. data/lib/puma/control_cli.rb +3 -6
  32. data/lib/puma/detect.rb +4 -0
  33. data/lib/puma/dsl.rb +110 -52
  34. data/lib/puma/error_logger.rb +17 -9
  35. data/lib/puma/events.rb +6 -126
  36. data/lib/puma/io_buffer.rb +39 -4
  37. data/lib/puma/jruby_restart.rb +2 -1
  38. data/lib/puma/launcher/bundle_pruner.rb +104 -0
  39. data/lib/puma/launcher.rb +100 -175
  40. data/lib/puma/log_writer.rb +141 -0
  41. data/lib/puma/minissl/context_builder.rb +23 -12
  42. data/lib/puma/minissl.rb +82 -11
  43. data/lib/puma/plugin/systemd.rb +90 -0
  44. data/lib/puma/plugin/tmp_restart.rb +1 -1
  45. data/lib/puma/rack/builder.rb +4 -4
  46. data/lib/puma/rack_default.rb +19 -4
  47. data/lib/puma/reactor.rb +4 -4
  48. data/lib/puma/request.rb +344 -165
  49. data/lib/puma/runner.rb +52 -20
  50. data/lib/puma/sd_notify.rb +149 -0
  51. data/lib/puma/server.rb +57 -71
  52. data/lib/puma/single.rb +13 -11
  53. data/lib/puma/state_file.rb +1 -4
  54. data/lib/puma/thread_pool.rb +16 -16
  55. data/lib/puma/util.rb +0 -11
  56. data/lib/puma.rb +12 -11
  57. data/lib/rack/handler/puma.rb +115 -94
  58. metadata +10 -5
  59. data/lib/puma/queue_close.rb +0 -26
  60. data/lib/puma/systemd.rb +0 -46
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,35 @@ 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
+ # Load the systemd integration if we detect systemd's NOTIFY_SOCKET.
63
+ # Skip this on JRuby though, because it is incompatible with the systemd
64
+ # integration due to https://github.com/jruby/jruby/issues/6504
65
+ if ENV["NOTIFY_SOCKET"] && !Puma.jruby?
66
+ @config.plugins.create('systemd')
67
+ end
68
+
62
69
  if @config.options[:bind_to_activated_sockets]
63
70
  @config.options[:binds] = @binder.synthesize_binds_from_activated_fs(
64
71
  @config.options[:binds],
@@ -69,8 +76,8 @@ module Puma
69
76
  @options = @config.options
70
77
  @config.clamp
71
78
 
72
- @events.formatter = Events::PidFormatter.new if clustered?
73
- @events.formatter = options[:log_formatter] if @options[:log_formatter]
79
+ @log_writer.formatter = LogWriter::PidFormatter.new if clustered?
80
+ @log_writer.formatter = options[:log_formatter] if @options[:log_formatter]
74
81
 
75
82
  generate_restart_data
76
83
 
@@ -80,17 +87,17 @@ module Puma
80
87
 
81
88
  Dir.chdir(@restart_dir)
82
89
 
83
- prune_bundler if prune_bundler?
90
+ prune_bundler!
84
91
 
85
92
  @environment = @options[:environment] if @options[:environment]
86
93
  set_rack_environment
87
94
 
88
95
  if clustered?
89
- @options[:logger] = @events
96
+ @options[:logger] = @log_writer
90
97
 
91
- @runner = Cluster.new(self, @events)
98
+ @runner = Cluster.new(self)
92
99
  else
93
- @runner = Single.new(self, @events)
100
+ @runner = Single.new(self)
94
101
  end
95
102
  Puma.stats_object = @runner
96
103
 
@@ -99,7 +106,7 @@ module Puma
99
106
  log_config if ENV['PUMA_LOG_CONFIG']
100
107
  end
101
108
 
102
- attr_reader :binder, :events, :config, :options, :restart_dir
109
+ attr_reader :binder, :log_writer, :events, :config, :options, :restart_dir
103
110
 
104
111
  # Return stats about the server
105
112
  def stats
@@ -115,7 +122,7 @@ module Puma
115
122
  permission = @options[:state_permission]
116
123
  return unless path
117
124
 
118
- require 'puma/state_file'
125
+ require_relative 'state_file'
119
126
 
120
127
  sf = StateFile.new
121
128
  sf.pid = Process.pid
@@ -172,16 +179,7 @@ module Puma
172
179
 
173
180
  # Run the server. This blocks until the server is stopped
174
181
  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
182
+ previous_env = get_env
185
183
 
186
184
  @config.clamp
187
185
 
@@ -189,24 +187,11 @@ module Puma
189
187
 
190
188
  setup_signals
191
189
  set_process_title
192
- integrate_with_systemd
190
+
191
+ # This blocks until the server is stopped
193
192
  @runner.run
194
193
 
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
194
+ do_run_finished(previous_env)
210
195
  end
211
196
 
212
197
  # Return all tcp ports the launcher may be using, TCP or SSL
@@ -250,30 +235,56 @@ module Puma
250
235
 
251
236
  private
252
237
 
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
238
+ def get_env
239
+ if defined?(Bundler)
240
+ env = Bundler::ORIGINAL_ENV.dup
241
+ # add -rbundler/setup so we load from Gemfile when restarting
242
+ bundle = "-rbundler/setup"
243
+ env["RUBYOPT"] = [env["RUBYOPT"], bundle].join(" ").lstrip unless env["RUBYOPT"].to_s.include?(bundle)
244
+ env
245
+ else
246
+ ENV.to_h
262
247
  end
263
248
  end
264
249
 
265
- def reload_worker_directory
266
- @runner.reload_worker_directory if @runner.respond_to?(:reload_worker_directory)
250
+ def do_run_finished(previous_env)
251
+ case @status
252
+ when :halt
253
+ do_forceful_stop
254
+ when :run, :stop
255
+ do_graceful_stop
256
+ when :restart
257
+ do_restart(previous_env)
258
+ end
259
+
260
+ close_binder_listeners unless @status == :restart
261
+ end
262
+
263
+ def do_forceful_stop
264
+ log "* Stopping immediately!"
265
+ @runner.stop_control
266
+ end
267
+
268
+ def do_graceful_stop
269
+ @events.fire_on_stopped!
270
+ @runner.stop_blocked
271
+ end
272
+
273
+ def do_restart(previous_env)
274
+ log "* Restarting..."
275
+ ENV.replace(previous_env)
276
+ @runner.stop_control
277
+ restart!
267
278
  end
268
279
 
269
280
  def restart!
270
281
  @events.fire_on_restart!
271
- @config.run_hooks :on_restart, self, @events
282
+ @config.run_hooks :on_restart, self, @log_writer
272
283
 
273
284
  if Puma.jruby?
274
285
  close_binder_listeners
275
286
 
276
- require 'puma/jruby_restart'
287
+ require_relative 'jruby_restart'
277
288
  JRubyRestart.chdir_exec(@restart_dir, restart_args)
278
289
  elsif Puma.windows?
279
290
  close_binder_listeners
@@ -290,94 +301,24 @@ module Puma
290
301
  end
291
302
  end
292
303
 
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
327
- end
328
-
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
345
- end
346
-
347
- #
348
- # Puma's systemd integration allows Puma to inform systemd:
349
- # 1. when it has successfully started
350
- # 2. when it is starting shutdown
351
- # 3. periodically for a liveness check with a watchdog thread
352
- #
353
-
354
- def integrate_with_systemd
355
- return unless ENV["NOTIFY_SOCKET"]
356
-
357
- begin
358
- require 'puma/systemd'
359
- rescue LoadError
360
- log "Systemd integration failed. It looks like you're trying to use systemd notify but don't have sd_notify gem installed"
361
- return
304
+ # If configured, write the pid of the current process out
305
+ # to a file.
306
+ def write_pid
307
+ path = @options[:pidfile]
308
+ return unless path
309
+ cur_pid = Process.pid
310
+ File.write path, cur_pid, mode: 'wb:UTF-8'
311
+ at_exit do
312
+ delete_pidfile if cur_pid == Process.pid
362
313
  end
363
-
364
- log "* Enabling systemd notification integration"
365
-
366
- systemd = Systemd.new(@events)
367
- systemd.hook_events
368
- systemd.start_watchdog
369
- end
370
-
371
- def spec_for_gem(gem_name)
372
- Bundler.rubygems.loaded_specs(gem_name)
373
314
  end
374
315
 
375
- def require_paths_for_gem(gem_spec)
376
- gem_spec.full_require_paths
316
+ def reload_worker_directory
317
+ @runner.reload_worker_directory if @runner.respond_to?(:reload_worker_directory)
377
318
  end
378
319
 
379
320
  def log(str)
380
- @events.log str
321
+ @log_writer.log(str)
381
322
  end
382
323
 
383
324
  def clustered?
@@ -385,15 +326,10 @@ module Puma
385
326
  end
386
327
 
387
328
  def unsupported(str)
388
- @events.error(str)
329
+ @log_writer.error(str)
389
330
  raise UnsupportedOption
390
331
  end
391
332
 
392
- def graceful_stop
393
- @events.fire_on_stopped!
394
- @runner.stop_blocked
395
- end
396
-
397
333
  def set_process_title
398
334
  Process.respond_to?(:setproctitle) ? Process.setproctitle(title) : $0 = title
399
335
  end
@@ -419,6 +355,11 @@ module Puma
419
355
  @options[:prune_bundler] && clustered? && !@options[:preload_app]
420
356
  end
421
357
 
358
+ def prune_bundler!
359
+ return unless prune_bundler?
360
+ BundlePruner.new(@original_argv, @options[:extra_runtime_dependencies], @log_writer).prune
361
+ end
362
+
422
363
  def generate_restart_data
423
364
  if dir = @options[:directory]
424
365
  @restart_dir = dir
@@ -485,7 +426,8 @@ module Puma
485
426
 
486
427
  begin
487
428
  Signal.trap "SIGTERM" do
488
- graceful_stop
429
+ # Shortcut the control flow in case raise_exception_on_sigterm is true
430
+ do_graceful_stop
489
431
 
490
432
  raise(SignalException, "SIGTERM") if @options[:raise_exception_on_sigterm]
491
433
  end
@@ -517,8 +459,8 @@ module Puma
517
459
  unless Puma.jruby? # INFO in use by JVM already
518
460
  Signal.trap "SIGINFO" do
519
461
  thread_status do |name, backtrace|
520
- @events.log name
521
- @events.log backtrace.map { |bt| " #{bt}" }
462
+ @log_writer.log(name)
463
+ @log_writer.log(backtrace.map { |bt| " #{bt}" })
522
464
  end
523
465
  end
524
466
  end
@@ -528,23 +470,6 @@ module Puma
528
470
  end
529
471
  end
530
472
 
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
473
  def log_config
549
474
  log "Configuration:"
550
475
 
@@ -0,0 +1,141 @@
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?
84
+ @debug
85
+ end
86
+
87
+ def debug(str)
88
+ log("% #{str}") if @debug
89
+ end
90
+
91
+ # Write +str+ to +@stderr+
92
+ def error(str)
93
+ @error_logger.info(text: @formatter.call("ERROR: #{str}"))
94
+ exit 1
95
+ end
96
+
97
+ def format(str)
98
+ formatter.call(str)
99
+ end
100
+
101
+ # An HTTP connection error has occurred.
102
+ # +error+ a connection exception, +req+ the request,
103
+ # and +text+ additional info
104
+ # @version 5.0.0
105
+ def connection_error(error, req, text="HTTP connection error")
106
+ @error_logger.info(error: error, req: req, text: text)
107
+ end
108
+
109
+ # An HTTP parse error has occurred.
110
+ # +error+ a parsing exception,
111
+ # and +req+ the request.
112
+ def parse_error(error, req)
113
+ @error_logger.info(error: error, req: req, text: 'HTTP parse error, malformed request')
114
+ end
115
+
116
+ # An SSL error has occurred.
117
+ # @param error <Puma::MiniSSL::SSLError>
118
+ # @param ssl_socket <Puma::MiniSSL::Socket>
119
+ def ssl_error(error, ssl_socket)
120
+ peeraddr = ssl_socket.peeraddr.last rescue "<unknown>"
121
+ peercert = ssl_socket.peercert
122
+ subject = peercert ? peercert.subject : nil
123
+ @error_logger.info(error: error, text: "SSL error, peer: #{peeraddr}, peer cert: #{subject}")
124
+ end
125
+
126
+ # An unknown error has occurred.
127
+ # +error+ an exception object, +req+ the request,
128
+ # and +text+ additional info
129
+ def unknown_error(error, req=nil, text="Unknown error")
130
+ @error_logger.info(error: error, req: req, text: text)
131
+ end
132
+
133
+ # Log occurred error debug dump.
134
+ # +error+ an exception object, +req+ the request,
135
+ # and +text+ additional info
136
+ # @version 5.0.0
137
+ def debug_error(error, req=nil, text="")
138
+ @error_logger.debug(error: error, req: req, text: text)
139
+ end
140
+ end
141
+ 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