puma 3.9.1 → 4.3.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.
- checksums.yaml +5 -5
- data/History.md +232 -0
- data/README.md +162 -224
- data/docs/architecture.md +37 -0
- data/{DEPLOYMENT.md → docs/deployment.md} +24 -4
- 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/plugins.md +38 -0
- data/docs/restart.md +41 -0
- data/docs/signals.md +56 -3
- data/docs/systemd.md +130 -37
- data/docs/tcp_mode.md +96 -0
- data/ext/puma_http11/PumaHttp11Service.java +2 -0
- data/ext/puma_http11/extconf.rb +13 -0
- data/ext/puma_http11/http11_parser.c +115 -140
- data/ext/puma_http11/http11_parser.java.rl +21 -37
- data/ext/puma_http11/http11_parser.rl +9 -9
- data/ext/puma_http11/http11_parser_common.rl +3 -3
- data/ext/puma_http11/mini_ssl.c +104 -8
- data/ext/puma_http11/org/jruby/puma/Http11.java +106 -114
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +90 -108
- data/ext/puma_http11/org/jruby/puma/IOBuffer.java +72 -0
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +21 -4
- data/ext/puma_http11/puma_http11.c +2 -0
- data/lib/puma.rb +16 -0
- data/lib/puma/accept_nonblock.rb +7 -1
- data/lib/puma/app/status.rb +40 -26
- data/lib/puma/binder.rb +57 -74
- data/lib/puma/cli.rb +26 -7
- data/lib/puma/client.rb +243 -190
- data/lib/puma/cluster.rb +78 -34
- data/lib/puma/commonlogger.rb +2 -0
- data/lib/puma/configuration.rb +24 -16
- data/lib/puma/const.rb +36 -18
- data/lib/puma/control_cli.rb +46 -19
- data/lib/puma/detect.rb +2 -0
- data/lib/puma/dsl.rb +329 -68
- data/lib/puma/events.rb +6 -1
- data/lib/puma/io_buffer.rb +3 -6
- data/lib/puma/jruby_restart.rb +2 -1
- data/lib/puma/launcher.rb +120 -58
- data/lib/puma/minissl.rb +69 -27
- data/lib/puma/minissl/context_builder.rb +76 -0
- data/lib/puma/null_io.rb +2 -0
- data/lib/puma/plugin.rb +7 -2
- data/lib/puma/plugin/tmp_restart.rb +2 -1
- data/lib/puma/rack/builder.rb +4 -1
- data/lib/puma/rack/urlmap.rb +2 -0
- data/lib/puma/rack_default.rb +2 -0
- data/lib/puma/reactor.rb +224 -34
- data/lib/puma/runner.rb +25 -4
- data/lib/puma/server.rb +148 -62
- data/lib/puma/single.rb +16 -5
- data/lib/puma/state_file.rb +2 -0
- data/lib/puma/tcp_logger.rb +2 -0
- data/lib/puma/thread_pool.rb +61 -38
- data/lib/puma/util.rb +2 -6
- data/lib/rack/handler/puma.rb +10 -4
- data/tools/docker/Dockerfile +16 -0
- data/tools/jungle/README.md +12 -2
- data/tools/jungle/init.d/README.md +2 -0
- data/tools/jungle/init.d/puma +8 -8
- data/tools/jungle/init.d/run-puma +1 -1
- data/tools/jungle/rc.d/README.md +74 -0
- data/tools/jungle/rc.d/puma +61 -0
- data/tools/jungle/rc.d/puma.conf +10 -0
- data/tools/trickletest.rb +1 -2
- metadata +29 -56
- data/.github/issue_template.md +0 -20
- data/Gemfile +0 -14
- data/Manifest.txt +0 -78
- data/Rakefile +0 -165
- data/Release.md +0 -9
- data/gemfiles/2.1-Gemfile +0 -12
- data/lib/puma/compat.rb +0 -14
- data/lib/puma/convenient.rb +0 -23
- data/lib/puma/daemon_ext.rb +0 -31
- data/lib/puma/delegation.rb +0 -11
- data/lib/puma/java_io_buffer.rb +0 -45
- data/lib/puma/rack/backports/uri/common_193.rb +0 -33
- data/puma.gemspec +0 -20
data/lib/puma/events.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'puma/const'
|
2
4
|
require "puma/null_io"
|
3
5
|
require 'stringio'
|
@@ -91,7 +93,10 @@ module Puma
|
|
91
93
|
# parsing exception.
|
92
94
|
#
|
93
95
|
def parse_error(server, env, error)
|
94
|
-
@stderr.puts "#{Time.now}: HTTP parse error, malformed request
|
96
|
+
@stderr.puts "#{Time.now}: HTTP parse error, malformed request " \
|
97
|
+
"(#{env[HTTP_X_FORWARDED_FOR] || env[REMOTE_ADDR]}#{env[REQUEST_PATH]}): " \
|
98
|
+
"#{error.inspect}" \
|
99
|
+
"\n---\n"
|
95
100
|
end
|
96
101
|
|
97
102
|
# An SSL error has occurred.
|
data/lib/puma/io_buffer.rb
CHANGED
data/lib/puma/jruby_restart.rb
CHANGED
data/lib/puma/launcher.rb
CHANGED
@@ -1,11 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'puma/events'
|
2
4
|
require 'puma/detect'
|
3
|
-
|
4
5
|
require 'puma/cluster'
|
5
6
|
require 'puma/single'
|
6
|
-
|
7
7
|
require 'puma/const'
|
8
|
-
|
9
8
|
require 'puma/binder'
|
10
9
|
|
11
10
|
module Puma
|
@@ -40,7 +39,7 @@ module Puma
|
|
40
39
|
# [200, {}, ["hello world"]]
|
41
40
|
# end
|
42
41
|
# end
|
43
|
-
# Puma::Launcher.new(conf,
|
42
|
+
# Puma::Launcher.new(conf, events: Puma::Events.stdio).run
|
44
43
|
def initialize(conf, launcher_args={})
|
45
44
|
@runner = nil
|
46
45
|
@events = launcher_args[:events] || Events::DEFAULT
|
@@ -61,10 +60,13 @@ module Puma
|
|
61
60
|
@options = @config.options
|
62
61
|
@config.clamp
|
63
62
|
|
63
|
+
@events.formatter = Events::PidFormatter.new if clustered?
|
64
|
+
@events.formatter = options[:log_formatter] if @options[:log_formatter]
|
65
|
+
|
64
66
|
generate_restart_data
|
65
67
|
|
66
|
-
if clustered? &&
|
67
|
-
unsupported
|
68
|
+
if clustered? && !Process.respond_to?(:fork)
|
69
|
+
unsupported "worker mode not supported on #{RUBY_ENGINE} on this platform"
|
68
70
|
end
|
69
71
|
|
70
72
|
if @options[:daemon] && Puma.windows?
|
@@ -79,13 +81,13 @@ module Puma
|
|
79
81
|
set_rack_environment
|
80
82
|
|
81
83
|
if clustered?
|
82
|
-
@events.formatter = Events::PidFormatter.new
|
83
84
|
@options[:logger] = @events
|
84
85
|
|
85
86
|
@runner = Cluster.new(self, @events)
|
86
87
|
else
|
87
88
|
@runner = Single.new(self, @events)
|
88
89
|
end
|
90
|
+
Puma.stats_object = @runner
|
89
91
|
|
90
92
|
@status = :run
|
91
93
|
end
|
@@ -121,19 +123,6 @@ module Puma
|
|
121
123
|
File.unlink(path) if path && File.exist?(path)
|
122
124
|
end
|
123
125
|
|
124
|
-
# If configured, write the pid of the current process out
|
125
|
-
# to a file.
|
126
|
-
def write_pid
|
127
|
-
path = @options[:pidfile]
|
128
|
-
return unless path
|
129
|
-
|
130
|
-
File.open(path, 'w') { |f| f.puts Process.pid }
|
131
|
-
cur = Process.pid
|
132
|
-
at_exit do
|
133
|
-
delete_pidfile if cur == Process.pid
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
126
|
# Begin async shutdown of the server
|
138
127
|
def halt
|
139
128
|
@status = :halt
|
@@ -163,7 +152,16 @@ module Puma
|
|
163
152
|
|
164
153
|
# Run the server. This blocks until the server is stopped
|
165
154
|
def run
|
166
|
-
previous_env =
|
155
|
+
previous_env =
|
156
|
+
if defined?(Bundler)
|
157
|
+
env = Bundler::ORIGINAL_ENV.dup
|
158
|
+
# add -rbundler/setup so we load from Gemfile when restarting
|
159
|
+
bundle = "-rbundler/setup"
|
160
|
+
env["RUBYOPT"] = [env["RUBYOPT"], bundle].join(" ").lstrip unless env["RUBYOPT"].to_s.include?(bundle)
|
161
|
+
env
|
162
|
+
else
|
163
|
+
ENV.to_h
|
164
|
+
end
|
167
165
|
|
168
166
|
@config.clamp
|
169
167
|
|
@@ -186,6 +184,7 @@ module Puma
|
|
186
184
|
when :exit
|
187
185
|
# nothing
|
188
186
|
end
|
187
|
+
@binder.close_unix_paths
|
189
188
|
end
|
190
189
|
|
191
190
|
# Return which tcp port the launcher is using, if it's using TCP
|
@@ -202,8 +201,25 @@ module Puma
|
|
202
201
|
end
|
203
202
|
end
|
204
203
|
|
204
|
+
def close_binder_listeners
|
205
|
+
@binder.close_listeners
|
206
|
+
end
|
207
|
+
|
205
208
|
private
|
206
209
|
|
210
|
+
# If configured, write the pid of the current process out
|
211
|
+
# to a file.
|
212
|
+
def write_pid
|
213
|
+
path = @options[:pidfile]
|
214
|
+
return unless path
|
215
|
+
|
216
|
+
File.open(path, 'w') { |f| f.puts Process.pid }
|
217
|
+
cur = Process.pid
|
218
|
+
at_exit do
|
219
|
+
delete_pidfile if cur == Process.pid
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
207
223
|
def reload_worker_directory
|
208
224
|
@runner.reload_worker_directory if @runner.respond_to?(:reload_worker_directory)
|
209
225
|
end
|
@@ -223,48 +239,71 @@ module Puma
|
|
223
239
|
Dir.chdir(@restart_dir)
|
224
240
|
Kernel.exec(*argv)
|
225
241
|
else
|
226
|
-
redirects = {:close_others => true}
|
227
|
-
@binder.listeners.each_with_index do |(l, io), i|
|
228
|
-
ENV["PUMA_INHERIT_#{i}"] = "#{io.to_i}:#{l}"
|
229
|
-
redirects[io.to_i] = io.to_i
|
230
|
-
end
|
231
|
-
|
232
242
|
argv = restart_args
|
233
243
|
Dir.chdir(@restart_dir)
|
234
|
-
argv += [
|
244
|
+
argv += [@binder.redirects_for_restart]
|
235
245
|
Kernel.exec(*argv)
|
236
246
|
end
|
237
247
|
end
|
238
248
|
|
239
|
-
def
|
240
|
-
|
241
|
-
|
242
|
-
|
249
|
+
def dependencies_and_files_to_require_after_prune
|
250
|
+
puma = spec_for_gem("puma")
|
251
|
+
|
252
|
+
deps = puma.runtime_dependencies.map do |d|
|
253
|
+
"#{d.name}:#{spec_for_gem(d.name).version}"
|
254
|
+
end
|
255
|
+
|
256
|
+
[deps, require_paths_for_gem(puma) + extra_runtime_deps_directories]
|
257
|
+
end
|
258
|
+
|
259
|
+
def extra_runtime_deps_directories
|
260
|
+
Array(@options[:extra_runtime_dependencies]).map do |d_name|
|
261
|
+
if (spec = spec_for_gem(d_name))
|
262
|
+
require_paths_for_gem(spec)
|
263
|
+
else
|
264
|
+
log "* Could not load extra dependency: #{d_name}"
|
265
|
+
nil
|
266
|
+
end
|
267
|
+
end.flatten.compact
|
268
|
+
end
|
269
|
+
|
270
|
+
def puma_wild_location
|
271
|
+
puma = spec_for_gem("puma")
|
272
|
+
dirs = require_paths_for_gem(puma)
|
243
273
|
puma_lib_dir = dirs.detect { |x| File.exist? File.join(x, '../bin/puma-wild') }
|
274
|
+
File.expand_path(File.join(puma_lib_dir, "../bin/puma-wild"))
|
275
|
+
end
|
244
276
|
|
245
|
-
|
277
|
+
def prune_bundler
|
278
|
+
return unless defined?(Bundler)
|
279
|
+
require_rubygems_min_version!(Gem::Version.new("2.2"), "prune_bundler")
|
280
|
+
unless puma_wild_location
|
246
281
|
log "! Unable to prune Bundler environment, continuing"
|
247
282
|
return
|
248
283
|
end
|
249
284
|
|
250
|
-
deps =
|
251
|
-
spec = Bundler.rubygems.loaded_specs(d.name)
|
252
|
-
"#{d.name}:#{spec.version.to_s}"
|
253
|
-
end
|
285
|
+
deps, dirs = dependencies_and_files_to_require_after_prune
|
254
286
|
|
255
287
|
log '* Pruning Bundler environment'
|
256
288
|
home = ENV['GEM_HOME']
|
257
289
|
Bundler.with_clean_env do
|
258
290
|
ENV['GEM_HOME'] = home
|
259
291
|
ENV['PUMA_BUNDLER_PRUNED'] = '1'
|
260
|
-
|
261
|
-
args = [Gem.ruby, wild, '-I', dirs.join(':'), deps.join(',')] + @original_argv
|
292
|
+
args = [Gem.ruby, puma_wild_location, '-I', dirs.join(':'), deps.join(',')] + @original_argv
|
262
293
|
# Ruby 2.0+ defaults to true which breaks socket activation
|
263
|
-
args += [{:close_others => false}]
|
294
|
+
args += [{:close_others => false}]
|
264
295
|
Kernel.exec(*args)
|
265
296
|
end
|
266
297
|
end
|
267
298
|
|
299
|
+
def spec_for_gem(gem_name)
|
300
|
+
Bundler.rubygems.loaded_specs(gem_name)
|
301
|
+
end
|
302
|
+
|
303
|
+
def require_paths_for_gem(gem_spec)
|
304
|
+
gem_spec.full_require_paths
|
305
|
+
end
|
306
|
+
|
268
307
|
def log(str)
|
269
308
|
@events.log str
|
270
309
|
end
|
@@ -284,13 +323,28 @@ module Puma
|
|
284
323
|
log "- Goodbye!"
|
285
324
|
end
|
286
325
|
|
326
|
+
def log_thread_status
|
327
|
+
Thread.list.each do |thread|
|
328
|
+
log "Thread TID-#{thread.object_id.to_s(36)} #{thread['label']}"
|
329
|
+
logstr = "Thread: TID-#{thread.object_id.to_s(36)}"
|
330
|
+
logstr += " #{thread.name}" if thread.respond_to?(:name)
|
331
|
+
log logstr
|
332
|
+
|
333
|
+
if thread.backtrace
|
334
|
+
log thread.backtrace.join("\n")
|
335
|
+
else
|
336
|
+
log "<no backtrace available>"
|
337
|
+
end
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
287
341
|
def set_process_title
|
288
342
|
Process.respond_to?(:setproctitle) ? Process.setproctitle(title) : $0 = title
|
289
343
|
end
|
290
344
|
|
291
345
|
def title
|
292
|
-
buffer
|
293
|
-
buffer
|
346
|
+
buffer = "puma #{Puma::Const::VERSION} (#{@options[:binds].join(',')})"
|
347
|
+
buffer += " [#{@options[:tag]}]" if @options[:tag] && !@options[:tag].empty?
|
294
348
|
buffer
|
295
349
|
end
|
296
350
|
|
@@ -307,16 +361,6 @@ module Puma
|
|
307
361
|
@options[:prune_bundler] && clustered? && !@options[:preload_app]
|
308
362
|
end
|
309
363
|
|
310
|
-
def close_binder_listeners
|
311
|
-
@binder.listeners.each do |l, io|
|
312
|
-
io.close
|
313
|
-
uri = URI.parse(l)
|
314
|
-
next unless uri.scheme == 'unix'
|
315
|
-
File.unlink("#{uri.host}#{uri.path}")
|
316
|
-
end
|
317
|
-
end
|
318
|
-
|
319
|
-
|
320
364
|
def generate_restart_data
|
321
365
|
if dir = @options[:directory]
|
322
366
|
@restart_dir = dir
|
@@ -383,12 +427,22 @@ module Puma
|
|
383
427
|
|
384
428
|
begin
|
385
429
|
Signal.trap "SIGTERM" do
|
386
|
-
|
430
|
+
graceful_stop
|
431
|
+
|
432
|
+
raise(SignalException, "SIGTERM") if @options[:raise_exception_on_sigterm]
|
387
433
|
end
|
388
434
|
rescue Exception
|
389
435
|
log "*** SIGTERM not implemented, signal based gracefully stopping unavailable!"
|
390
436
|
end
|
391
437
|
|
438
|
+
begin
|
439
|
+
Signal.trap "SIGINT" do
|
440
|
+
stop
|
441
|
+
end
|
442
|
+
rescue Exception
|
443
|
+
log "*** SIGINT not implemented, signal based gracefully stopping unavailable!"
|
444
|
+
end
|
445
|
+
|
392
446
|
begin
|
393
447
|
Signal.trap "SIGHUP" do
|
394
448
|
if @runner.redirected_io?
|
@@ -401,13 +455,21 @@ module Puma
|
|
401
455
|
log "*** SIGHUP not implemented, signal based logs reopening unavailable!"
|
402
456
|
end
|
403
457
|
|
404
|
-
|
405
|
-
Signal.trap
|
406
|
-
|
407
|
-
graceful_stop
|
408
|
-
exit
|
458
|
+
begin
|
459
|
+
Signal.trap "SIGINFO" do
|
460
|
+
log_thread_status
|
409
461
|
end
|
462
|
+
rescue Exception
|
463
|
+
# Not going to log this one, as SIGINFO is *BSD only and would be pretty annoying
|
464
|
+
# to see this constantly on Linux.
|
410
465
|
end
|
411
466
|
end
|
467
|
+
|
468
|
+
def require_rubygems_min_version!(min_version, feature)
|
469
|
+
return if min_version <= Gem::Version.new(Gem::VERSION)
|
470
|
+
|
471
|
+
raise "#{feature} is not supported on your version of RubyGems. " \
|
472
|
+
"You must have RubyGems #{min_version}+ to use this feature."
|
473
|
+
end
|
412
474
|
end
|
413
475
|
end
|
data/lib/puma/minissl.rb
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'io/wait'
|
5
|
+
rescue LoadError
|
6
|
+
end
|
7
|
+
|
1
8
|
module Puma
|
2
9
|
module MiniSSL
|
3
10
|
class Socket
|
@@ -11,6 +18,10 @@ module Puma
|
|
11
18
|
@socket
|
12
19
|
end
|
13
20
|
|
21
|
+
def closed?
|
22
|
+
@socket.closed?
|
23
|
+
end
|
24
|
+
|
14
25
|
def readpartial(size)
|
15
26
|
while true
|
16
27
|
output = @engine.read
|
@@ -43,7 +54,21 @@ module Puma
|
|
43
54
|
output = engine_read_all
|
44
55
|
return output if output
|
45
56
|
|
46
|
-
data = @socket.read_nonblock(size)
|
57
|
+
data = @socket.read_nonblock(size, exception: false)
|
58
|
+
if data == :wait_readable || data == :wait_writable
|
59
|
+
# It would make more sense to let @socket.read_nonblock raise
|
60
|
+
# EAGAIN if necessary but it seems like it'll misbehave on Windows.
|
61
|
+
# I don't have a Windows machine to debug this so I can't explain
|
62
|
+
# exactly whats happening in that OS. Please let me know if you
|
63
|
+
# find out!
|
64
|
+
#
|
65
|
+
# In the meantime, we can emulate the correct behavior by
|
66
|
+
# capturing :wait_readable & :wait_writable and raising EAGAIN
|
67
|
+
# ourselves.
|
68
|
+
raise IO::EAGAINWaitReadable
|
69
|
+
elsif data.nil?
|
70
|
+
return nil
|
71
|
+
end
|
47
72
|
|
48
73
|
@engine.inject(data)
|
49
74
|
output = engine_read_all
|
@@ -57,6 +82,8 @@ module Puma
|
|
57
82
|
end
|
58
83
|
|
59
84
|
def write(data)
|
85
|
+
return 0 if data.empty?
|
86
|
+
|
60
87
|
need = data.bytesize
|
61
88
|
|
62
89
|
while true
|
@@ -96,35 +123,29 @@ module Puma
|
|
96
123
|
@socket.flush
|
97
124
|
end
|
98
125
|
|
99
|
-
def
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
return unless IO.select([@socket], nil, nil, 1)
|
108
|
-
begin
|
109
|
-
read_nonblock(1024)
|
110
|
-
rescue Errno::EAGAIN
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
done = @engine.shutdown
|
115
|
-
|
116
|
-
while true
|
117
|
-
enc = @engine.extract
|
118
|
-
@socket.write enc
|
119
|
-
|
120
|
-
notify = @socket.sysread(1024)
|
126
|
+
def read_and_drop(timeout = 1)
|
127
|
+
return :timeout unless IO.select([@socket], nil, nil, timeout)
|
128
|
+
return :eof unless read_nonblock(1024)
|
129
|
+
:drop
|
130
|
+
rescue Errno::EAGAIN
|
131
|
+
# do nothing
|
132
|
+
:eagain
|
133
|
+
end
|
121
134
|
|
122
|
-
|
123
|
-
|
135
|
+
def should_drop_bytes?
|
136
|
+
@engine.init? || !@engine.shutdown
|
137
|
+
end
|
124
138
|
|
125
|
-
|
139
|
+
def close
|
140
|
+
begin
|
141
|
+
# Read any drop any partially initialized sockets and any received bytes during shutdown.
|
142
|
+
# Don't let this socket hold this loop forever.
|
143
|
+
# If it can't send more packets within 1s, then give up.
|
144
|
+
while should_drop_bytes?
|
145
|
+
return if [:timeout, :eof].include?(read_and_drop(1))
|
126
146
|
end
|
127
147
|
rescue IOError, SystemCallError
|
148
|
+
Thread.current.purge_interrupt_queue if Thread.current.respond_to? :purge_interrupt_queue
|
128
149
|
# nothing
|
129
150
|
ensure
|
130
151
|
@socket.close
|
@@ -155,11 +176,18 @@ module Puma
|
|
155
176
|
|
156
177
|
class Context
|
157
178
|
attr_accessor :verify_mode
|
179
|
+
attr_reader :no_tlsv1, :no_tlsv1_1
|
180
|
+
|
181
|
+
def initialize
|
182
|
+
@no_tlsv1 = false
|
183
|
+
@no_tlsv1_1 = false
|
184
|
+
end
|
158
185
|
|
159
186
|
if defined?(JRUBY_VERSION)
|
160
187
|
# jruby-specific Context properties: java uses a keystore and password pair rather than a cert/key pair
|
161
188
|
attr_reader :keystore
|
162
189
|
attr_accessor :keystore_pass
|
190
|
+
attr_accessor :ssl_cipher_list
|
163
191
|
|
164
192
|
def keystore=(keystore)
|
165
193
|
raise ArgumentError, "No such keystore file '#{keystore}'" unless File.exist? keystore
|
@@ -175,6 +203,7 @@ module Puma
|
|
175
203
|
attr_reader :key
|
176
204
|
attr_reader :cert
|
177
205
|
attr_reader :ca
|
206
|
+
attr_accessor :ssl_cipher_filter
|
178
207
|
|
179
208
|
def key=(key)
|
180
209
|
raise ArgumentError, "No such key file '#{key}'" unless File.exist? key
|
@@ -196,6 +225,19 @@ module Puma
|
|
196
225
|
raise "Cert not configured" unless @cert
|
197
226
|
end
|
198
227
|
end
|
228
|
+
|
229
|
+
# disables TLSv1
|
230
|
+
def no_tlsv1=(tlsv1)
|
231
|
+
raise ArgumentError, "Invalid value of no_tlsv1" unless ['true', 'false', true, false].include?(tlsv1)
|
232
|
+
@no_tlsv1 = tlsv1
|
233
|
+
end
|
234
|
+
|
235
|
+
# disables TLSv1 and TLSv1.1. Overrides `#no_tlsv1=`
|
236
|
+
def no_tlsv1_1=(tlsv1_1)
|
237
|
+
raise ArgumentError, "Invalid value of no_tlsv1" unless ['true', 'false', true, false].include?(tlsv1_1)
|
238
|
+
@no_tlsv1_1 = tlsv1_1
|
239
|
+
end
|
240
|
+
|
199
241
|
end
|
200
242
|
|
201
243
|
VERIFY_NONE = 0
|
@@ -229,7 +271,7 @@ module Puma
|
|
229
271
|
end
|
230
272
|
|
231
273
|
def close
|
232
|
-
@socket.close
|
274
|
+
@socket.close unless @socket.closed? # closed? call is for Windows
|
233
275
|
end
|
234
276
|
end
|
235
277
|
end
|