puma 5.6.4-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 +136 -3
- data/README.md +21 -17
- data/bin/puma-wild +1 -1
- data/docs/compile_options.md +34 -0
- data/docs/fork_worker.md +1 -3
- data/docs/testing_benchmarks_local_files.md +150 -0
- data/docs/testing_test_rackup_ci_files.md +36 -0
- data/ext/puma_http11/extconf.rb +18 -10
- 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 +63 -24
- data/ext/puma_http11/org/jruby/puma/Http11.java +3 -3
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +1 -1
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +166 -65
- data/ext/puma_http11/puma_http11.c +17 -9
- data/lib/puma/app/status.rb +6 -3
- data/lib/puma/binder.rb +37 -43
- data/lib/puma/cli.rb +11 -17
- data/lib/puma/client.rb +22 -12
- 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/configuration.rb +74 -58
- data/lib/puma/const.rb +14 -18
- data/lib/puma/control_cli.rb +21 -18
- data/lib/puma/detect.rb +2 -0
- data/lib/puma/dsl.rb +94 -49
- 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/launcher/bundle_pruner.rb +104 -0
- data/lib/puma/launcher.rb +107 -156
- data/lib/puma/log_writer.rb +137 -0
- data/lib/puma/minissl/context_builder.rb +23 -12
- data/lib/puma/minissl.rb +91 -15
- data/lib/puma/null_io.rb +5 -0
- data/lib/puma/plugin/tmp_restart.rb +1 -1
- data/lib/puma/puma_http11.jar +0 -0
- data/lib/puma/rack/builder.rb +4 -4
- data/lib/puma/rack_default.rb +1 -1
- data/lib/puma/reactor.rb +3 -3
- data/lib/puma/request.rb +291 -156
- data/lib/puma/runner.rb +41 -20
- data/lib/puma/server.rb +53 -64
- data/lib/puma/single.rb +10 -10
- data/lib/puma/state_file.rb +2 -4
- data/lib/puma/systemd.rb +3 -2
- data/lib/puma/thread_pool.rb +16 -13
- data/lib/puma/util.rb +12 -14
- data/lib/puma.rb +11 -8
- data/lib/rack/handler/puma.rb +9 -9
- metadata +7 -3
- 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
|
-
|
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
|
@@ -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
|
-
|
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
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
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
|
255
|
-
|
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, @
|
276
|
+
@config.run_hooks :on_restart, self, @log_writer
|
261
277
|
|
262
278
|
if Puma.jruby?
|
263
279
|
close_binder_listeners
|
264
280
|
|
265
|
-
|
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
|
-
#
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
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
|
-
|
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
|
-
|
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
|
-
@
|
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
|
-
@
|
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
|
-
|
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
|
-
@
|
510
|
-
@
|
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,
|
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
|