puma 3.12.1 → 5.3.2
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 +1414 -448
- data/LICENSE +23 -20
- data/README.md +131 -60
- data/bin/puma-wild +3 -9
- data/docs/architecture.md +24 -19
- data/docs/compile_options.md +19 -0
- data/docs/deployment.md +38 -13
- data/docs/fork_worker.md +33 -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 +20 -10
- data/docs/rails_dev_mode.md +29 -0
- data/docs/restart.md +47 -22
- data/docs/signals.md +7 -6
- data/docs/stats.md +142 -0
- data/docs/systemd.md +48 -70
- data/ext/puma_http11/PumaHttp11Service.java +2 -2
- data/ext/puma_http11/ext_help.h +1 -1
- data/ext/puma_http11/extconf.rb +27 -0
- data/ext/puma_http11/http11_parser.c +84 -109
- 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 +3 -3
- data/ext/puma_http11/mini_ssl.c +254 -91
- 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 +89 -106
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +92 -22
- data/ext/puma_http11/puma_http11.c +34 -50
- data/lib/puma.rb +54 -0
- data/lib/puma/app/status.rb +68 -49
- data/lib/puma/binder.rb +191 -139
- data/lib/puma/cli.rb +15 -15
- data/lib/puma/client.rb +257 -228
- data/lib/puma/cluster.rb +221 -212
- data/lib/puma/cluster/worker.rb +183 -0
- data/lib/puma/cluster/worker_handle.rb +90 -0
- data/lib/puma/commonlogger.rb +2 -2
- data/lib/puma/configuration.rb +58 -51
- data/lib/puma/const.rb +39 -19
- data/lib/puma/control_cli.rb +109 -67
- data/lib/puma/detect.rb +24 -3
- data/lib/puma/dsl.rb +519 -121
- 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.rb +96 -0
- data/lib/puma/launcher.rb +178 -68
- data/lib/puma/minissl.rb +147 -48
- data/lib/puma/minissl/context_builder.rb +79 -0
- data/lib/puma/null_io.rb +13 -1
- data/lib/puma/plugin.rb +6 -12
- data/lib/puma/plugin/tmp_restart.rb +2 -0
- data/lib/puma/queue_close.rb +26 -0
- data/lib/puma/rack/builder.rb +2 -4
- 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 +467 -0
- data/lib/puma/runner.rb +31 -52
- data/lib/puma/server.rb +282 -680
- data/lib/puma/single.rb +11 -67
- data/lib/puma/state_file.rb +8 -3
- data/lib/puma/systemd.rb +46 -0
- data/lib/puma/thread_pool.rb +129 -81
- data/lib/puma/util.rb +13 -6
- data/lib/rack/handler/puma.rb +5 -6
- data/tools/Dockerfile +16 -0
- data/tools/trickletest.rb +0 -1
- metadata +42 -26
- 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
@@ -0,0 +1,183 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Puma
|
4
|
+
class Cluster < Puma::Runner
|
5
|
+
# This class is instantiated by the `Puma::Cluster` and represents a single
|
6
|
+
# worker process.
|
7
|
+
#
|
8
|
+
# At the core of this class is running an instance of `Puma::Server` which
|
9
|
+
# gets created via the `start_server` method from the `Puma::Runner` class
|
10
|
+
# that this inherits from.
|
11
|
+
class Worker < Puma::Runner
|
12
|
+
attr_reader :index, :master
|
13
|
+
|
14
|
+
def initialize(index:, master:, launcher:, pipes:, server: nil)
|
15
|
+
super launcher, launcher.events
|
16
|
+
|
17
|
+
@index = index
|
18
|
+
@master = master
|
19
|
+
@launcher = launcher
|
20
|
+
@options = launcher.options
|
21
|
+
@check_pipe = pipes[:check_pipe]
|
22
|
+
@worker_write = pipes[:worker_write]
|
23
|
+
@fork_pipe = pipes[:fork_pipe]
|
24
|
+
@wakeup = pipes[:wakeup]
|
25
|
+
@server = server
|
26
|
+
end
|
27
|
+
|
28
|
+
def run
|
29
|
+
title = "puma: cluster worker #{index}: #{master}"
|
30
|
+
title += " [#{@options[:tag]}]" if @options[:tag] && !@options[:tag].empty?
|
31
|
+
$0 = title
|
32
|
+
|
33
|
+
Signal.trap "SIGINT", "IGNORE"
|
34
|
+
Signal.trap "SIGCHLD", "DEFAULT"
|
35
|
+
|
36
|
+
Thread.new do
|
37
|
+
Puma.set_thread_name "worker check pipe"
|
38
|
+
IO.select [@check_pipe]
|
39
|
+
log "! Detected parent died, dying"
|
40
|
+
exit! 1
|
41
|
+
end
|
42
|
+
|
43
|
+
# If we're not running under a Bundler context, then
|
44
|
+
# report the info about the context we will be using
|
45
|
+
if !ENV['BUNDLE_GEMFILE']
|
46
|
+
if File.exist?("Gemfile")
|
47
|
+
log "+ Gemfile in context: #{File.expand_path("Gemfile")}"
|
48
|
+
elsif File.exist?("gems.rb")
|
49
|
+
log "+ Gemfile in context: #{File.expand_path("gems.rb")}"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Invoke any worker boot hooks so they can get
|
54
|
+
# things in shape before booting the app.
|
55
|
+
@launcher.config.run_hooks :before_worker_boot, index, @launcher.events
|
56
|
+
|
57
|
+
begin
|
58
|
+
server = @server ||= start_server
|
59
|
+
rescue Exception => e
|
60
|
+
log "! Unable to start worker"
|
61
|
+
log e.backtrace[0]
|
62
|
+
exit 1
|
63
|
+
end
|
64
|
+
|
65
|
+
restart_server = Queue.new << true << false
|
66
|
+
|
67
|
+
fork_worker = @options[:fork_worker] && index == 0
|
68
|
+
|
69
|
+
if fork_worker
|
70
|
+
restart_server.clear
|
71
|
+
worker_pids = []
|
72
|
+
Signal.trap "SIGCHLD" do
|
73
|
+
wakeup! if worker_pids.reject! do |p|
|
74
|
+
Process.wait(p, Process::WNOHANG) rescue true
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
Thread.new do
|
79
|
+
Puma.set_thread_name "worker fork pipe"
|
80
|
+
while (idx = @fork_pipe.gets)
|
81
|
+
idx = idx.to_i
|
82
|
+
if idx == -1 # stop server
|
83
|
+
if restart_server.length > 0
|
84
|
+
restart_server.clear
|
85
|
+
server.begin_restart(true)
|
86
|
+
@launcher.config.run_hooks :before_refork, nil, @launcher.events
|
87
|
+
Puma::Util.nakayoshi_gc @events if @options[:nakayoshi_fork]
|
88
|
+
end
|
89
|
+
elsif idx == 0 # restart server
|
90
|
+
restart_server << true << false
|
91
|
+
else # fork worker
|
92
|
+
worker_pids << pid = spawn_worker(idx)
|
93
|
+
@worker_write << "f#{pid}:#{idx}\n" rescue nil
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
Signal.trap "SIGTERM" do
|
100
|
+
@worker_write << "e#{Process.pid}\n" rescue nil
|
101
|
+
restart_server.clear
|
102
|
+
server.stop
|
103
|
+
restart_server << false
|
104
|
+
end
|
105
|
+
|
106
|
+
begin
|
107
|
+
@worker_write << "b#{Process.pid}:#{index}\n"
|
108
|
+
rescue SystemCallError, IOError
|
109
|
+
Thread.current.purge_interrupt_queue if Thread.current.respond_to? :purge_interrupt_queue
|
110
|
+
STDERR.puts "Master seems to have exited, exiting."
|
111
|
+
return
|
112
|
+
end
|
113
|
+
|
114
|
+
while restart_server.pop
|
115
|
+
server_thread = server.run
|
116
|
+
stat_thread ||= Thread.new(@worker_write) do |io|
|
117
|
+
Puma.set_thread_name "stat payload"
|
118
|
+
base_payload = "p#{Process.pid}"
|
119
|
+
|
120
|
+
while true
|
121
|
+
begin
|
122
|
+
b = server.backlog || 0
|
123
|
+
r = server.running || 0
|
124
|
+
t = server.pool_capacity || 0
|
125
|
+
m = server.max_threads || 0
|
126
|
+
rc = server.requests_count || 0
|
127
|
+
payload = %Q!#{base_payload}{ "backlog":#{b}, "running":#{r}, "pool_capacity":#{t}, "max_threads": #{m}, "requests_count": #{rc} }\n!
|
128
|
+
io << payload
|
129
|
+
rescue IOError
|
130
|
+
Thread.current.purge_interrupt_queue if Thread.current.respond_to? :purge_interrupt_queue
|
131
|
+
break
|
132
|
+
end
|
133
|
+
sleep Const::WORKER_CHECK_INTERVAL
|
134
|
+
end
|
135
|
+
end
|
136
|
+
server_thread.join
|
137
|
+
end
|
138
|
+
|
139
|
+
# Invoke any worker shutdown hooks so they can prevent the worker
|
140
|
+
# exiting until any background operations are completed
|
141
|
+
@launcher.config.run_hooks :before_worker_shutdown, index, @launcher.events
|
142
|
+
ensure
|
143
|
+
@worker_write << "t#{Process.pid}\n" rescue nil
|
144
|
+
@worker_write.close
|
145
|
+
end
|
146
|
+
|
147
|
+
private
|
148
|
+
|
149
|
+
def spawn_worker(idx)
|
150
|
+
@launcher.config.run_hooks :before_worker_fork, idx, @launcher.events
|
151
|
+
|
152
|
+
pid = fork do
|
153
|
+
new_worker = Worker.new index: idx,
|
154
|
+
master: master,
|
155
|
+
launcher: @launcher,
|
156
|
+
pipes: { check_pipe: @check_pipe,
|
157
|
+
worker_write: @worker_write },
|
158
|
+
server: @server
|
159
|
+
new_worker.run
|
160
|
+
end
|
161
|
+
|
162
|
+
if !pid
|
163
|
+
log "! Complete inability to spawn new workers detected"
|
164
|
+
log "! Seppuku is the only choice."
|
165
|
+
exit! 1
|
166
|
+
end
|
167
|
+
|
168
|
+
@launcher.config.run_hooks :after_worker_fork, idx, @launcher.events
|
169
|
+
pid
|
170
|
+
end
|
171
|
+
|
172
|
+
def wakeup!
|
173
|
+
return unless @wakeup
|
174
|
+
|
175
|
+
begin
|
176
|
+
@wakeup.write "!" unless @wakeup.closed?
|
177
|
+
rescue SystemCallError, IOError
|
178
|
+
Thread.current.purge_interrupt_queue if Thread.current.respond_to? :purge_interrupt_queue
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Puma
|
4
|
+
class Cluster < Runner
|
5
|
+
# This class represents a worker process from the perspective of the puma
|
6
|
+
# master process. It contains information about the process and its health
|
7
|
+
# and it exposes methods to control the process via IPC. It does not
|
8
|
+
# include the actual logic executed by the worker process itself. For that,
|
9
|
+
# see Puma::Cluster::Worker.
|
10
|
+
class WorkerHandle
|
11
|
+
def initialize(idx, pid, phase, options)
|
12
|
+
@index = idx
|
13
|
+
@pid = pid
|
14
|
+
@phase = phase
|
15
|
+
@stage = :started
|
16
|
+
@signal = "TERM"
|
17
|
+
@options = options
|
18
|
+
@first_term_sent = nil
|
19
|
+
@started_at = Time.now
|
20
|
+
@last_checkin = Time.now
|
21
|
+
@last_status = {}
|
22
|
+
@term = false
|
23
|
+
end
|
24
|
+
|
25
|
+
attr_reader :index, :pid, :phase, :signal, :last_checkin, :last_status, :started_at
|
26
|
+
|
27
|
+
# @version 5.0.0
|
28
|
+
attr_writer :pid, :phase
|
29
|
+
|
30
|
+
def booted?
|
31
|
+
@stage == :booted
|
32
|
+
end
|
33
|
+
|
34
|
+
def uptime
|
35
|
+
Time.now - started_at
|
36
|
+
end
|
37
|
+
|
38
|
+
def boot!
|
39
|
+
@last_checkin = Time.now
|
40
|
+
@stage = :booted
|
41
|
+
end
|
42
|
+
|
43
|
+
def term?
|
44
|
+
@term
|
45
|
+
end
|
46
|
+
|
47
|
+
def ping!(status)
|
48
|
+
@last_checkin = Time.now
|
49
|
+
captures = status.match(/{ "backlog":(?<backlog>\d*), "running":(?<running>\d*), "pool_capacity":(?<pool_capacity>\d*), "max_threads": (?<max_threads>\d*), "requests_count": (?<requests_count>\d*) }/)
|
50
|
+
@last_status = captures.names.inject({}) do |hash, key|
|
51
|
+
hash[key.to_sym] = captures[key].to_i
|
52
|
+
hash
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# @see Puma::Cluster#check_workers
|
57
|
+
# @version 5.0.0
|
58
|
+
def ping_timeout
|
59
|
+
@last_checkin +
|
60
|
+
(booted? ?
|
61
|
+
@options[:worker_timeout] :
|
62
|
+
@options[:worker_boot_timeout]
|
63
|
+
)
|
64
|
+
end
|
65
|
+
|
66
|
+
def term
|
67
|
+
begin
|
68
|
+
if @first_term_sent && (Time.now - @first_term_sent) > @options[:worker_shutdown_timeout]
|
69
|
+
@signal = "KILL"
|
70
|
+
else
|
71
|
+
@term ||= true
|
72
|
+
@first_term_sent ||= Time.now
|
73
|
+
end
|
74
|
+
Process.kill @signal, @pid if @pid
|
75
|
+
rescue Errno::ESRCH
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def kill
|
80
|
+
@signal = 'KILL'
|
81
|
+
term
|
82
|
+
end
|
83
|
+
|
84
|
+
def hup
|
85
|
+
Process.kill "HUP", @pid
|
86
|
+
rescue Errno::ESRCH
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
data/lib/puma/commonlogger.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
module Puma
|
4
4
|
# Rack::CommonLogger forwards every request to the given +app+, and
|
5
5
|
# logs a line in the
|
6
|
-
# {Apache common log format}[
|
6
|
+
# {Apache common log format}[https://httpd.apache.org/docs/1.3/logs.html#common]
|
7
7
|
# to the +logger+.
|
8
8
|
#
|
9
9
|
# If +logger+ is nil, CommonLogger will fall back +rack.errors+, which is
|
@@ -16,7 +16,7 @@ module Puma
|
|
16
16
|
# (which is called without arguments in order to make the error appear for
|
17
17
|
# sure)
|
18
18
|
class CommonLogger
|
19
|
-
# Common Log Format:
|
19
|
+
# Common Log Format: https://httpd.apache.org/docs/1.3/logs.html#common
|
20
20
|
#
|
21
21
|
# lilith.local - - [07/Aug/2006 23:58:02 -0400] "GET / HTTP/1.1" 500 -
|
22
22
|
#
|
data/lib/puma/configuration.rb
CHANGED
@@ -20,7 +20,7 @@ module Puma
|
|
20
20
|
# In this class any "user" specified options take precedence over any
|
21
21
|
# "file" specified options, take precedence over any "default" options.
|
22
22
|
#
|
23
|
-
# User input is
|
23
|
+
# User input is preferred over "defaults":
|
24
24
|
# user_options = { foo: "bar" }
|
25
25
|
# default_options = { foo: "zoo" }
|
26
26
|
# options = UserFileDefaultOptions.new(user_options, default_options)
|
@@ -32,7 +32,7 @@ module Puma
|
|
32
32
|
# puts options.all_of(:foo)
|
33
33
|
# # => ["bar", "zoo"]
|
34
34
|
#
|
35
|
-
# A "file" option can be set. This config will be
|
35
|
+
# A "file" option can be set. This config will be preferred over "default" options
|
36
36
|
# but will defer to any available "user" specified options.
|
37
37
|
#
|
38
38
|
# user_options = { foo: "bar" }
|
@@ -54,9 +54,7 @@ module Puma
|
|
54
54
|
attr_reader :user_options, :file_options, :default_options
|
55
55
|
|
56
56
|
def [](key)
|
57
|
-
|
58
|
-
return file_options[key] if file_options.key?(key)
|
59
|
-
return default_options[key] if default_options.key?(key)
|
57
|
+
fetch(key)
|
60
58
|
end
|
61
59
|
|
62
60
|
def []=(key, value)
|
@@ -64,7 +62,11 @@ module Puma
|
|
64
62
|
end
|
65
63
|
|
66
64
|
def fetch(key, default_value = nil)
|
67
|
-
|
65
|
+
return user_options[key] if user_options.key?(key)
|
66
|
+
return file_options[key] if file_options.key?(key)
|
67
|
+
return default_options[key] if default_options.key?(key)
|
68
|
+
|
69
|
+
default_value
|
68
70
|
end
|
69
71
|
|
70
72
|
def all_of(key)
|
@@ -90,6 +92,12 @@ module Puma
|
|
90
92
|
end
|
91
93
|
end
|
92
94
|
end
|
95
|
+
|
96
|
+
def final_options
|
97
|
+
default_options
|
98
|
+
.merge(file_options)
|
99
|
+
.merge(user_options)
|
100
|
+
end
|
93
101
|
end
|
94
102
|
|
95
103
|
# The main configuration class of Puma.
|
@@ -106,16 +114,17 @@ module Puma
|
|
106
114
|
#
|
107
115
|
# It also handles loading plugins.
|
108
116
|
#
|
109
|
-
#
|
117
|
+
# [Note:]
|
118
|
+
# `:port` and `:host` are not valid keys. By the time they make it to the
|
110
119
|
# configuration options they are expected to be incorporated into a `:binds` key.
|
111
120
|
# Under the hood the DSL maps `port` and `host` calls to `:binds`
|
112
121
|
#
|
113
|
-
#
|
114
|
-
#
|
115
|
-
#
|
116
|
-
#
|
117
|
-
#
|
118
|
-
#
|
122
|
+
# config = Configuration.new({}) do |user_config, file_config, default_config|
|
123
|
+
# user_config.port 3003
|
124
|
+
# end
|
125
|
+
# config.load
|
126
|
+
# puts config.options[:port]
|
127
|
+
# # => 3003
|
119
128
|
#
|
120
129
|
# It is expected that `load` is called on the configuration instance after setting
|
121
130
|
# config. This method expands any values in `config_file` and puts them into the
|
@@ -137,6 +146,10 @@ module Puma
|
|
137
146
|
@file_dsl = DSL.new(@options.file_options, self)
|
138
147
|
@default_dsl = DSL.new(@options.default_options, self)
|
139
148
|
|
149
|
+
if !@options[:prune_bundler]
|
150
|
+
default_options[:preload_app] = (@options[:workers] > 1) && Puma.forkable?
|
151
|
+
end
|
152
|
+
|
140
153
|
if block
|
141
154
|
configure(&block)
|
142
155
|
end
|
@@ -167,26 +180,35 @@ module Puma
|
|
167
180
|
self
|
168
181
|
end
|
169
182
|
|
183
|
+
# @version 5.0.0
|
184
|
+
def default_max_threads
|
185
|
+
Puma.mri? ? 5 : 16
|
186
|
+
end
|
187
|
+
|
170
188
|
def puma_default_options
|
171
189
|
{
|
172
|
-
:min_threads => 0,
|
173
|
-
:max_threads =>
|
190
|
+
:min_threads => Integer(ENV['PUMA_MIN_THREADS'] || ENV['MIN_THREADS'] || 0),
|
191
|
+
:max_threads => Integer(ENV['PUMA_MAX_THREADS'] || ENV['MAX_THREADS'] || default_max_threads),
|
174
192
|
:log_requests => false,
|
175
193
|
:debug => false,
|
176
194
|
:binds => ["tcp://#{DefaultTCPHost}:#{DefaultTCPPort}"],
|
177
|
-
:workers => 0,
|
178
|
-
:
|
195
|
+
:workers => Integer(ENV['WEB_CONCURRENCY'] || 0),
|
196
|
+
:silence_single_worker_warning => false,
|
179
197
|
:mode => :http,
|
180
198
|
:worker_timeout => DefaultWorkerTimeout,
|
181
199
|
:worker_boot_timeout => DefaultWorkerTimeout,
|
182
200
|
:worker_shutdown_timeout => DefaultWorkerShutdownTimeout,
|
183
201
|
:remote_address => :socket,
|
184
202
|
:tag => method(:infer_tag),
|
185
|
-
:environment => -> { ENV['RACK_ENV'] || "development" },
|
203
|
+
:environment => -> { ENV['RACK_ENV'] || ENV['RAILS_ENV'] || "development" },
|
186
204
|
:rackup => DefaultRackup,
|
187
205
|
:logger => STDOUT,
|
188
206
|
:persistent_timeout => Const::PERSISTENT_TIMEOUT,
|
189
|
-
:first_data_timeout => Const::FIRST_DATA_TIMEOUT
|
207
|
+
:first_data_timeout => Const::FIRST_DATA_TIMEOUT,
|
208
|
+
:raise_exception_on_sigterm => true,
|
209
|
+
:max_fast_inline => Const::MAX_FAST_INLINE,
|
210
|
+
:io_selector_backend => :auto,
|
211
|
+
:mutate_stdout_and_stderr_to_sync_on_write => true,
|
190
212
|
}
|
191
213
|
end
|
192
214
|
|
@@ -244,14 +266,6 @@ module Puma
|
|
244
266
|
def app
|
245
267
|
found = options[:app] || load_rackup
|
246
268
|
|
247
|
-
if @options[:mode] == :tcp
|
248
|
-
require 'puma/tcp_logger'
|
249
|
-
|
250
|
-
logger = @options[:logger]
|
251
|
-
quiet = !@options[:log_requests]
|
252
|
-
return TCPLogger.new(logger, found, quiet)
|
253
|
-
end
|
254
|
-
|
255
269
|
if @options[:log_requests]
|
256
270
|
require 'puma/commonlogger'
|
257
271
|
logger = @options[:logger]
|
@@ -274,8 +288,19 @@ module Puma
|
|
274
288
|
@plugins.create name
|
275
289
|
end
|
276
290
|
|
277
|
-
def run_hooks(key, arg)
|
278
|
-
@options.all_of(key).each
|
291
|
+
def run_hooks(key, arg, events)
|
292
|
+
@options.all_of(key).each do |b|
|
293
|
+
begin
|
294
|
+
b.call arg
|
295
|
+
rescue => e
|
296
|
+
events.log "WARNING hook #{key} failed with exception (#{e.class}) #{e.message}"
|
297
|
+
events.debug e.backtrace.join("\n")
|
298
|
+
end
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
def final_options
|
303
|
+
@options.final_options
|
279
304
|
end
|
280
305
|
|
281
306
|
def self.temp_path
|
@@ -318,6 +343,8 @@ module Puma
|
|
318
343
|
raise "Missing rackup file '#{rackup}'" unless File.exist?(rackup)
|
319
344
|
|
320
345
|
rack_app, rack_options = rack_builder.parse_file(rackup)
|
346
|
+
rack_options = rack_options || {}
|
347
|
+
|
321
348
|
@options.file_options.merge!(rack_options)
|
322
349
|
|
323
350
|
config_ru_binds = []
|
@@ -331,29 +358,9 @@ module Puma
|
|
331
358
|
end
|
332
359
|
|
333
360
|
def self.random_token
|
334
|
-
|
335
|
-
require 'openssl'
|
336
|
-
rescue LoadError
|
337
|
-
end
|
338
|
-
|
339
|
-
count = 16
|
340
|
-
|
341
|
-
bytes = nil
|
342
|
-
|
343
|
-
if defined? OpenSSL::Random
|
344
|
-
bytes = OpenSSL::Random.random_bytes(count)
|
345
|
-
elsif File.exist?("/dev/urandom")
|
346
|
-
File.open('/dev/urandom') { |f| bytes = f.read(count) }
|
347
|
-
end
|
348
|
-
|
349
|
-
if bytes
|
350
|
-
token = "".dup
|
351
|
-
bytes.each_byte { |b| token << b.to_s(16) }
|
352
|
-
else
|
353
|
-
token = (0..count).to_a.map { rand(255).to_s(16) }.join
|
354
|
-
end
|
361
|
+
require 'securerandom' unless defined?(SecureRandom)
|
355
362
|
|
356
|
-
|
363
|
+
SecureRandom.hex(16)
|
357
364
|
end
|
358
365
|
end
|
359
366
|
end
|