puma 3.12.1 → 5.6.4
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 +1553 -447
- data/LICENSE +23 -20
- data/README.md +175 -63
- data/bin/puma-wild +3 -9
- data/docs/architecture.md +59 -21
- data/docs/compile_options.md +21 -0
- data/docs/deployment.md +69 -58
- data/docs/fork_worker.md +33 -0
- data/docs/images/puma-connection-flow-no-reactor.png +0 -0
- data/docs/images/puma-connection-flow.png +0 -0
- data/docs/images/puma-general-arch.png +0 -0
- data/docs/jungle/README.md +9 -0
- data/{tools → docs}/jungle/rc.d/README.md +1 -1
- data/{tools → docs}/jungle/rc.d/puma +2 -2
- data/{tools → docs}/jungle/rc.d/puma.conf +0 -0
- data/docs/kubernetes.md +66 -0
- data/docs/nginx.md +1 -1
- data/docs/plugins.md +22 -12
- data/docs/rails_dev_mode.md +28 -0
- data/docs/restart.md +47 -22
- data/docs/signals.md +13 -11
- data/docs/stats.md +142 -0
- data/docs/systemd.md +95 -120
- data/ext/puma_http11/PumaHttp11Service.java +2 -2
- data/ext/puma_http11/ext_help.h +1 -1
- data/ext/puma_http11/extconf.rb +51 -1
- data/ext/puma_http11/http11_parser.c +105 -117
- data/ext/puma_http11/http11_parser.h +1 -1
- data/ext/puma_http11/http11_parser.java.rl +22 -38
- data/ext/puma_http11/http11_parser.rl +4 -2
- data/ext/puma_http11/http11_parser_common.rl +4 -4
- data/ext/puma_http11/mini_ssl.c +319 -96
- data/ext/puma_http11/no_ssl/PumaHttp11Service.java +15 -0
- data/ext/puma_http11/org/jruby/puma/Http11.java +108 -116
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +84 -99
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +120 -65
- data/ext/puma_http11/puma_http11.c +35 -51
- data/lib/puma/app/status.rb +68 -49
- data/lib/puma/binder.rb +234 -137
- data/lib/puma/cli.rb +28 -18
- data/lib/puma/client.rb +343 -230
- data/lib/puma/cluster/worker.rb +173 -0
- data/lib/puma/cluster/worker_handle.rb +94 -0
- data/lib/puma/cluster.rb +247 -232
- data/lib/puma/commonlogger.rb +2 -2
- data/lib/puma/configuration.rb +61 -51
- data/lib/puma/const.rb +42 -21
- data/lib/puma/control_cli.rb +109 -67
- data/lib/puma/detect.rb +29 -2
- data/lib/puma/dsl.rb +615 -123
- data/lib/puma/error_logger.rb +104 -0
- data/lib/puma/events.rb +55 -31
- data/lib/puma/io_buffer.rb +7 -5
- data/lib/puma/jruby_restart.rb +0 -58
- data/lib/puma/json_serialization.rb +96 -0
- data/lib/puma/launcher.rb +182 -69
- data/lib/puma/minissl/context_builder.rb +81 -0
- data/lib/puma/minissl.rb +161 -61
- data/lib/puma/null_io.rb +13 -1
- data/lib/puma/plugin/tmp_restart.rb +2 -0
- data/lib/puma/plugin.rb +7 -13
- data/lib/puma/queue_close.rb +26 -0
- data/lib/puma/rack/builder.rb +3 -5
- data/lib/puma/rack/urlmap.rb +2 -0
- data/lib/puma/rack_default.rb +2 -0
- data/lib/puma/reactor.rb +85 -316
- data/lib/puma/request.rb +472 -0
- data/lib/puma/runner.rb +48 -55
- data/lib/puma/server.rb +303 -695
- data/lib/puma/single.rb +11 -67
- data/lib/puma/state_file.rb +47 -8
- data/lib/puma/systemd.rb +46 -0
- data/lib/puma/thread_pool.rb +132 -82
- data/lib/puma/util.rb +21 -7
- data/lib/puma.rb +54 -0
- data/lib/rack/handler/puma.rb +5 -6
- data/tools/Dockerfile +16 -0
- data/tools/trickletest.rb +0 -1
- metadata +45 -29
- data/ext/puma_http11/io_buffer.c +0 -155
- data/lib/puma/accept_nonblock.rb +0 -23
- data/lib/puma/compat.rb +0 -14
- data/lib/puma/convenient.rb +0 -25
- data/lib/puma/daemon_ext.rb +0 -33
- data/lib/puma/delegation.rb +0 -13
- data/lib/puma/java_io_buffer.rb +0 -47
- data/lib/puma/rack/backports/uri/common_193.rb +0 -33
- data/lib/puma/tcp_logger.rb +0 -41
- data/tools/jungle/README.md +0 -19
- data/tools/jungle/init.d/README.md +0 -61
- data/tools/jungle/init.d/puma +0 -421
- data/tools/jungle/init.d/run-puma +0 -18
- data/tools/jungle/upstart/README.md +0 -61
- data/tools/jungle/upstart/puma-manager.conf +0 -31
- data/tools/jungle/upstart/puma.conf +0 -69
data/lib/puma/launcher.rb
CHANGED
@@ -2,12 +2,9 @@
|
|
2
2
|
|
3
3
|
require 'puma/events'
|
4
4
|
require 'puma/detect'
|
5
|
-
|
6
5
|
require 'puma/cluster'
|
7
6
|
require 'puma/single'
|
8
|
-
|
9
7
|
require 'puma/const'
|
10
|
-
|
11
8
|
require 'puma/binder'
|
12
9
|
|
13
10
|
module Puma
|
@@ -18,6 +15,7 @@ module Puma
|
|
18
15
|
# It is responsible for either launching a cluster of Puma workers or a single
|
19
16
|
# puma server.
|
20
17
|
class Launcher
|
18
|
+
# @deprecated 6.0.0
|
21
19
|
KEYS_NOT_TO_PERSIST_IN_STATE = [
|
22
20
|
:logger, :lowlevel_error_handler,
|
23
21
|
:before_worker_shutdown, :before_worker_boot, :before_worker_fork,
|
@@ -50,8 +48,9 @@ module Puma
|
|
50
48
|
@original_argv = @argv.dup
|
51
49
|
@config = conf
|
52
50
|
|
53
|
-
@binder = Binder.new(@events)
|
54
|
-
@binder.
|
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 }
|
55
54
|
|
56
55
|
@environment = conf.environment
|
57
56
|
|
@@ -60,19 +59,25 @@ module Puma
|
|
60
59
|
|
61
60
|
@config.load
|
62
61
|
|
62
|
+
if @config.options[:bind_to_activated_sockets]
|
63
|
+
@config.options[:binds] = @binder.synthesize_binds_from_activated_fs(
|
64
|
+
@config.options[:binds],
|
65
|
+
@config.options[:bind_to_activated_sockets] == 'only'
|
66
|
+
)
|
67
|
+
end
|
68
|
+
|
63
69
|
@options = @config.options
|
64
70
|
@config.clamp
|
65
71
|
|
72
|
+
@events.formatter = Events::PidFormatter.new if clustered?
|
73
|
+
@events.formatter = options[:log_formatter] if @options[:log_formatter]
|
74
|
+
|
66
75
|
generate_restart_data
|
67
76
|
|
68
|
-
if clustered? && !
|
77
|
+
if clustered? && !Puma.forkable?
|
69
78
|
unsupported "worker mode not supported on #{RUBY_ENGINE} on this platform"
|
70
79
|
end
|
71
80
|
|
72
|
-
if @options[:daemon] && Puma.windows?
|
73
|
-
unsupported 'daemon mode not supported on Windows'
|
74
|
-
end
|
75
|
-
|
76
81
|
Dir.chdir(@restart_dir)
|
77
82
|
|
78
83
|
prune_bundler if prune_bundler?
|
@@ -81,7 +86,6 @@ module Puma
|
|
81
86
|
set_rack_environment
|
82
87
|
|
83
88
|
if clustered?
|
84
|
-
@events.formatter = Events::PidFormatter.new
|
85
89
|
@options[:logger] = @events
|
86
90
|
|
87
91
|
@runner = Cluster.new(self, @events)
|
@@ -91,6 +95,8 @@ module Puma
|
|
91
95
|
Puma.stats_object = @runner
|
92
96
|
|
93
97
|
@status = :run
|
98
|
+
|
99
|
+
log_config if ENV['PUMA_LOG_CONFIG']
|
94
100
|
end
|
95
101
|
|
96
102
|
attr_reader :binder, :events, :config, :options, :restart_dir
|
@@ -106,6 +112,7 @@ module Puma
|
|
106
112
|
write_pid
|
107
113
|
|
108
114
|
path = @options[:state]
|
115
|
+
permission = @options[:state_permission]
|
109
116
|
return unless path
|
110
117
|
|
111
118
|
require 'puma/state_file'
|
@@ -114,8 +121,9 @@ module Puma
|
|
114
121
|
sf.pid = Process.pid
|
115
122
|
sf.control_url = @options[:control_url]
|
116
123
|
sf.control_auth_token = @options[:control_auth_token]
|
124
|
+
sf.running_from = File.expand_path('.')
|
117
125
|
|
118
|
-
sf.save path
|
126
|
+
sf.save path, permission
|
119
127
|
end
|
120
128
|
|
121
129
|
# Delete the configured pidfile
|
@@ -124,19 +132,6 @@ module Puma
|
|
124
132
|
File.unlink(path) if path && File.exist?(path)
|
125
133
|
end
|
126
134
|
|
127
|
-
# If configured, write the pid of the current process out
|
128
|
-
# to a file.
|
129
|
-
def write_pid
|
130
|
-
path = @options[:pidfile]
|
131
|
-
return unless path
|
132
|
-
|
133
|
-
File.open(path, 'w') { |f| f.puts Process.pid }
|
134
|
-
cur = Process.pid
|
135
|
-
at_exit do
|
136
|
-
delete_pidfile if cur == Process.pid
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
135
|
# Begin async shutdown of the server
|
141
136
|
def halt
|
142
137
|
@status = :halt
|
@@ -183,28 +178,34 @@ module Puma
|
|
183
178
|
|
184
179
|
setup_signals
|
185
180
|
set_process_title
|
181
|
+
integrate_with_systemd
|
186
182
|
@runner.run
|
187
183
|
|
188
184
|
case @status
|
189
185
|
when :halt
|
190
186
|
log "* Stopping immediately!"
|
187
|
+
@runner.stop_control
|
191
188
|
when :run, :stop
|
192
189
|
graceful_stop
|
193
190
|
when :restart
|
194
191
|
log "* Restarting..."
|
195
192
|
ENV.replace(previous_env)
|
196
|
-
@runner.
|
193
|
+
@runner.stop_control
|
197
194
|
restart!
|
198
195
|
when :exit
|
199
196
|
# nothing
|
200
197
|
end
|
198
|
+
close_binder_listeners unless @status == :restart
|
201
199
|
end
|
202
200
|
|
203
|
-
# Return
|
204
|
-
|
205
|
-
|
201
|
+
# Return all tcp ports the launcher may be using, TCP or SSL
|
202
|
+
# @!attribute [r] connected_ports
|
203
|
+
# @version 5.0.0
|
204
|
+
def connected_ports
|
205
|
+
@binder.connected_ports
|
206
206
|
end
|
207
207
|
|
208
|
+
# @!attribute [r] restart_args
|
208
209
|
def restart_args
|
209
210
|
cmd = @options[:restart_cmd]
|
210
211
|
if cmd
|
@@ -214,14 +215,49 @@ module Puma
|
|
214
215
|
end
|
215
216
|
end
|
216
217
|
|
218
|
+
def close_binder_listeners
|
219
|
+
@runner.close_control_listeners
|
220
|
+
@binder.close_listeners
|
221
|
+
unless @status == :restart
|
222
|
+
log "=== puma shutdown: #{Time.now} ==="
|
223
|
+
log "- Goodbye!"
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
# @!attribute [r] thread_status
|
228
|
+
# @version 5.0.0
|
229
|
+
def thread_status
|
230
|
+
Thread.list.each do |thread|
|
231
|
+
name = "Thread: TID-#{thread.object_id.to_s(36)}"
|
232
|
+
name += " #{thread['label']}" if thread['label']
|
233
|
+
name += " #{thread.name}" if thread.respond_to?(:name) && thread.name
|
234
|
+
backtrace = thread.backtrace || ["<no backtrace available>"]
|
235
|
+
|
236
|
+
yield name, backtrace
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
217
240
|
private
|
218
241
|
|
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
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
219
254
|
def reload_worker_directory
|
220
255
|
@runner.reload_worker_directory if @runner.respond_to?(:reload_worker_directory)
|
221
256
|
end
|
222
257
|
|
223
258
|
def restart!
|
224
|
-
@
|
259
|
+
@events.fire_on_restart!
|
260
|
+
@config.run_hooks :on_restart, self, @events
|
225
261
|
|
226
262
|
if Puma.jruby?
|
227
263
|
close_binder_listeners
|
@@ -235,48 +271,100 @@ module Puma
|
|
235
271
|
Dir.chdir(@restart_dir)
|
236
272
|
Kernel.exec(*argv)
|
237
273
|
else
|
238
|
-
redirects = {:close_others => true}
|
239
|
-
@binder.listeners.each_with_index do |(l, io), i|
|
240
|
-
ENV["PUMA_INHERIT_#{i}"] = "#{io.to_i}:#{l}"
|
241
|
-
redirects[io.to_i] = io.to_i
|
242
|
-
end
|
243
|
-
|
244
274
|
argv = restart_args
|
245
275
|
Dir.chdir(@restart_dir)
|
246
|
-
|
276
|
+
ENV.update(@binder.redirects_for_restart_env)
|
277
|
+
argv += [@binder.redirects_for_restart]
|
247
278
|
Kernel.exec(*argv)
|
248
279
|
end
|
249
280
|
end
|
250
281
|
|
251
|
-
|
252
|
-
|
253
|
-
puma =
|
254
|
-
|
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)
|
255
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
|
256
308
|
|
257
|
-
|
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
|
258
314
|
log "! Unable to prune Bundler environment, continuing"
|
259
315
|
return
|
260
316
|
end
|
261
317
|
|
262
|
-
|
263
|
-
spec = Bundler.rubygems.loaded_specs(d.name)
|
264
|
-
"#{d.name}:#{spec.version.to_s}"
|
265
|
-
end
|
318
|
+
dirs = files_to_require_after_prune
|
266
319
|
|
267
320
|
log '* Pruning Bundler environment'
|
268
321
|
home = ENV['GEM_HOME']
|
269
|
-
Bundler.
|
322
|
+
bundle_gemfile = Bundler.original_env['BUNDLE_GEMFILE']
|
323
|
+
bundle_app_config = Bundler.original_env['BUNDLE_APP_CONFIG']
|
324
|
+
with_unbundled_env do
|
270
325
|
ENV['GEM_HOME'] = home
|
326
|
+
ENV['BUNDLE_GEMFILE'] = bundle_gemfile
|
271
327
|
ENV['PUMA_BUNDLER_PRUNED'] = '1'
|
272
|
-
|
273
|
-
args = [Gem.ruby,
|
328
|
+
ENV["BUNDLE_APP_CONFIG"] = bundle_app_config
|
329
|
+
args = [Gem.ruby, puma_wild_location, '-I', dirs.join(':')] + @original_argv
|
274
330
|
# Ruby 2.0+ defaults to true which breaks socket activation
|
275
|
-
args += [{:close_others => false}]
|
331
|
+
args += [{:close_others => false}]
|
276
332
|
Kernel.exec(*args)
|
277
333
|
end
|
278
334
|
end
|
279
335
|
|
336
|
+
#
|
337
|
+
# Puma's systemd integration allows Puma to inform systemd:
|
338
|
+
# 1. when it has successfully started
|
339
|
+
# 2. when it is starting shutdown
|
340
|
+
# 3. periodically for a liveness check with a watchdog thread
|
341
|
+
#
|
342
|
+
|
343
|
+
def integrate_with_systemd
|
344
|
+
return unless ENV["NOTIFY_SOCKET"]
|
345
|
+
|
346
|
+
begin
|
347
|
+
require 'puma/systemd'
|
348
|
+
rescue LoadError
|
349
|
+
log "Systemd integration failed. It looks like you're trying to use systemd notify but don't have sd_notify gem installed"
|
350
|
+
return
|
351
|
+
end
|
352
|
+
|
353
|
+
log "* Enabling systemd notification integration"
|
354
|
+
|
355
|
+
systemd = Systemd.new(@events)
|
356
|
+
systemd.hook_events
|
357
|
+
systemd.start_watchdog
|
358
|
+
end
|
359
|
+
|
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
|
+
|
280
368
|
def log(str)
|
281
369
|
@events.log str
|
282
370
|
end
|
@@ -291,15 +379,15 @@ module Puma
|
|
291
379
|
end
|
292
380
|
|
293
381
|
def graceful_stop
|
382
|
+
@events.fire_on_stopped!
|
294
383
|
@runner.stop_blocked
|
295
|
-
log "=== puma shutdown: #{Time.now} ==="
|
296
|
-
log "- Goodbye!"
|
297
384
|
end
|
298
385
|
|
299
386
|
def set_process_title
|
300
387
|
Process.respond_to?(:setproctitle) ? Process.setproctitle(title) : $0 = title
|
301
388
|
end
|
302
389
|
|
390
|
+
# @!attribute [r] title
|
303
391
|
def title
|
304
392
|
buffer = "puma #{Puma::Const::VERSION} (#{@options[:binds].join(',')})"
|
305
393
|
buffer += " [#{@options[:tag]}]" if @options[:tag] && !@options[:tag].empty?
|
@@ -311,6 +399,7 @@ module Puma
|
|
311
399
|
ENV['RACK_ENV'] = environment
|
312
400
|
end
|
313
401
|
|
402
|
+
# @!attribute [r] environment
|
314
403
|
def environment
|
315
404
|
@environment
|
316
405
|
end
|
@@ -319,16 +408,6 @@ module Puma
|
|
319
408
|
@options[:prune_bundler] && clustered? && !@options[:preload_app]
|
320
409
|
end
|
321
410
|
|
322
|
-
def close_binder_listeners
|
323
|
-
@binder.listeners.each do |l, io|
|
324
|
-
io.close
|
325
|
-
uri = URI.parse(l)
|
326
|
-
next unless uri.scheme == 'unix'
|
327
|
-
File.unlink("#{uri.host}#{uri.path}")
|
328
|
-
end
|
329
|
-
end
|
330
|
-
|
331
|
-
|
332
411
|
def generate_restart_data
|
333
412
|
if dir = @options[:directory]
|
334
413
|
@restart_dir = dir
|
@@ -397,7 +476,7 @@ module Puma
|
|
397
476
|
Signal.trap "SIGTERM" do
|
398
477
|
graceful_stop
|
399
478
|
|
400
|
-
raise
|
479
|
+
raise(SignalException, "SIGTERM") if @options[:raise_exception_on_sigterm]
|
401
480
|
end
|
402
481
|
rescue Exception
|
403
482
|
log "*** SIGTERM not implemented, signal based gracefully stopping unavailable!"
|
@@ -405,12 +484,6 @@ module Puma
|
|
405
484
|
|
406
485
|
begin
|
407
486
|
Signal.trap "SIGINT" do
|
408
|
-
if Puma.jruby?
|
409
|
-
@status = :exit
|
410
|
-
graceful_stop
|
411
|
-
exit
|
412
|
-
end
|
413
|
-
|
414
487
|
stop
|
415
488
|
end
|
416
489
|
rescue Exception
|
@@ -428,6 +501,46 @@ module Puma
|
|
428
501
|
rescue Exception
|
429
502
|
log "*** SIGHUP not implemented, signal based logs reopening unavailable!"
|
430
503
|
end
|
504
|
+
|
505
|
+
begin
|
506
|
+
unless Puma.jruby? # INFO in use by JVM already
|
507
|
+
Signal.trap "SIGINFO" do
|
508
|
+
thread_status do |name, backtrace|
|
509
|
+
@events.log name
|
510
|
+
@events.log backtrace.map { |bt| " #{bt}" }
|
511
|
+
end
|
512
|
+
end
|
513
|
+
end
|
514
|
+
rescue Exception
|
515
|
+
# Not going to log this one, as SIGINFO is *BSD only and would be pretty annoying
|
516
|
+
# to see this constantly on Linux.
|
517
|
+
end
|
518
|
+
end
|
519
|
+
|
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
|
+
def log_config
|
538
|
+
log "Configuration:"
|
539
|
+
|
540
|
+
@config.final_options
|
541
|
+
.each { |config_key, value| log "- #{config_key}: #{value}" }
|
542
|
+
|
543
|
+
log "\n"
|
431
544
|
end
|
432
545
|
end
|
433
546
|
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module Puma
|
2
|
+
module MiniSSL
|
3
|
+
class ContextBuilder
|
4
|
+
def initialize(params, events)
|
5
|
+
@params = params
|
6
|
+
@events = events
|
7
|
+
end
|
8
|
+
|
9
|
+
def context
|
10
|
+
ctx = MiniSSL::Context.new
|
11
|
+
|
12
|
+
if defined?(JRUBY_VERSION)
|
13
|
+
unless params['keystore']
|
14
|
+
events.error "Please specify the Java keystore via 'keystore='"
|
15
|
+
end
|
16
|
+
|
17
|
+
ctx.keystore = params['keystore']
|
18
|
+
|
19
|
+
unless params['keystore-pass']
|
20
|
+
events.error "Please specify the Java keystore password via 'keystore-pass='"
|
21
|
+
end
|
22
|
+
|
23
|
+
ctx.keystore_pass = params['keystore-pass']
|
24
|
+
ctx.ssl_cipher_list = params['ssl_cipher_list'] if params['ssl_cipher_list']
|
25
|
+
else
|
26
|
+
if params['key'].nil? && params['key_pem'].nil?
|
27
|
+
events.error "Please specify the SSL key via 'key=' or 'key_pem='"
|
28
|
+
end
|
29
|
+
|
30
|
+
ctx.key = params['key'] if params['key']
|
31
|
+
ctx.key_pem = params['key_pem'] if params['key_pem']
|
32
|
+
|
33
|
+
if params['cert'].nil? && params['cert_pem'].nil?
|
34
|
+
events.error "Please specify the SSL cert via 'cert=' or 'cert_pem='"
|
35
|
+
end
|
36
|
+
|
37
|
+
ctx.cert = params['cert'] if params['cert']
|
38
|
+
ctx.cert_pem = params['cert_pem'] if params['cert_pem']
|
39
|
+
|
40
|
+
if ['peer', 'force_peer'].include?(params['verify_mode'])
|
41
|
+
unless params['ca']
|
42
|
+
events.error "Please specify the SSL ca via 'ca='"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
ctx.ca = params['ca'] if params['ca']
|
47
|
+
ctx.ssl_cipher_filter = params['ssl_cipher_filter'] if params['ssl_cipher_filter']
|
48
|
+
end
|
49
|
+
|
50
|
+
ctx.no_tlsv1 = true if params['no_tlsv1'] == 'true'
|
51
|
+
ctx.no_tlsv1_1 = true if params['no_tlsv1_1'] == 'true'
|
52
|
+
|
53
|
+
if params['verify_mode']
|
54
|
+
ctx.verify_mode = case params['verify_mode']
|
55
|
+
when "peer"
|
56
|
+
MiniSSL::VERIFY_PEER
|
57
|
+
when "force_peer"
|
58
|
+
MiniSSL::VERIFY_PEER | MiniSSL::VERIFY_FAIL_IF_NO_PEER_CERT
|
59
|
+
when "none"
|
60
|
+
MiniSSL::VERIFY_NONE
|
61
|
+
else
|
62
|
+
events.error "Please specify a valid verify_mode="
|
63
|
+
MiniSSL::VERIFY_NONE
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
if params['verification_flags']
|
68
|
+
ctx.verification_flags = params['verification_flags'].split(',').
|
69
|
+
map { |flag| MiniSSL::VERIFICATION_FLAGS.fetch(flag) }.
|
70
|
+
inject { |sum, flag| sum ? sum | flag : flag }
|
71
|
+
end
|
72
|
+
|
73
|
+
ctx
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
attr_reader :params, :events
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|