puma 3.11.1 → 6.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/History.md +2092 -422
- data/LICENSE +23 -20
- data/README.md +301 -69
- data/bin/puma-wild +3 -9
- data/docs/architecture.md +59 -21
- data/docs/compile_options.md +55 -0
- data/docs/deployment.md +69 -58
- data/docs/fork_worker.md +41 -0
- data/docs/java_options.md +54 -0
- data/docs/jungle/README.md +9 -0
- data/docs/jungle/rc.d/README.md +74 -0
- data/docs/jungle/rc.d/puma +61 -0
- data/docs/jungle/rc.d/puma.conf +10 -0
- data/docs/kubernetes.md +78 -0
- data/docs/nginx.md +2 -2
- data/docs/plugins.md +26 -12
- data/docs/rails_dev_mode.md +28 -0
- data/docs/restart.md +48 -22
- data/docs/signals.md +13 -11
- data/docs/stats.md +147 -0
- data/docs/systemd.md +108 -117
- data/docs/testing_benchmarks_local_files.md +150 -0
- data/docs/testing_test_rackup_ci_files.md +36 -0
- data/ext/puma_http11/PumaHttp11Service.java +2 -2
- data/ext/puma_http11/ext_help.h +1 -1
- data/ext/puma_http11/extconf.rb +68 -3
- data/ext/puma_http11/http11_parser.c +106 -118
- data/ext/puma_http11/http11_parser.h +2 -2
- data/ext/puma_http11/http11_parser.java.rl +22 -38
- data/ext/puma_http11/http11_parser.rl +6 -4
- data/ext/puma_http11/http11_parser_common.rl +6 -6
- data/ext/puma_http11/mini_ssl.c +474 -94
- data/ext/puma_http11/no_ssl/PumaHttp11Service.java +15 -0
- data/ext/puma_http11/org/jruby/puma/Http11.java +136 -121
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +84 -99
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +251 -88
- data/ext/puma_http11/puma_http11.c +53 -58
- data/lib/puma/app/status.rb +71 -49
- data/lib/puma/binder.rb +257 -151
- data/lib/puma/cli.rb +61 -38
- data/lib/puma/client.rb +464 -224
- data/lib/puma/cluster/worker.rb +183 -0
- data/lib/puma/cluster/worker_handle.rb +96 -0
- data/lib/puma/cluster.rb +343 -239
- data/lib/puma/commonlogger.rb +23 -14
- data/lib/puma/configuration.rb +144 -96
- data/lib/puma/const.rb +194 -115
- data/lib/puma/control_cli.rb +135 -81
- data/lib/puma/detect.rb +34 -2
- data/lib/puma/dsl.rb +1092 -153
- data/lib/puma/error_logger.rb +113 -0
- data/lib/puma/events.rb +17 -111
- data/lib/puma/io_buffer.rb +44 -5
- data/lib/puma/jruby_restart.rb +2 -73
- data/lib/puma/json_serialization.rb +96 -0
- data/lib/puma/launcher/bundle_pruner.rb +104 -0
- data/lib/puma/launcher.rb +205 -138
- data/lib/puma/log_writer.rb +147 -0
- data/lib/puma/minissl/context_builder.rb +96 -0
- data/lib/puma/minissl.rb +279 -70
- data/lib/puma/null_io.rb +61 -2
- data/lib/puma/plugin/systemd.rb +90 -0
- data/lib/puma/plugin/tmp_restart.rb +3 -1
- data/lib/puma/plugin.rb +9 -13
- data/lib/puma/rack/builder.rb +10 -11
- data/lib/puma/rack/urlmap.rb +3 -1
- data/lib/puma/rack_default.rb +21 -4
- data/lib/puma/reactor.rb +97 -185
- data/lib/puma/request.rb +688 -0
- data/lib/puma/runner.rb +114 -69
- data/lib/puma/sd_notify.rb +146 -0
- data/lib/puma/server.rb +409 -704
- data/lib/puma/single.rb +29 -72
- data/lib/puma/state_file.rb +48 -9
- data/lib/puma/thread_pool.rb +234 -93
- data/lib/puma/util.rb +23 -10
- data/lib/puma.rb +68 -5
- data/lib/rack/handler/puma.rb +119 -86
- data/tools/Dockerfile +16 -0
- data/tools/trickletest.rb +0 -1
- metadata +55 -33
- 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 -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/lib/puma/tcp_logger.rb +0 -39
- data/tools/jungle/README.md +0 -13
- data/tools/jungle/init.d/README.md +0 -59
- 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/commonlogger.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Puma
|
2
4
|
# Rack::CommonLogger forwards every request to the given +app+, and
|
3
5
|
# logs a line in the
|
4
|
-
# {Apache common log format}[
|
6
|
+
# {Apache common log format}[https://httpd.apache.org/docs/2.4/logs.html#common]
|
5
7
|
# to the +logger+.
|
6
8
|
#
|
7
9
|
# If +logger+ is nil, CommonLogger will fall back +rack.errors+, which is
|
@@ -14,7 +16,7 @@ module Puma
|
|
14
16
|
# (which is called without arguments in order to make the error appear for
|
15
17
|
# sure)
|
16
18
|
class CommonLogger
|
17
|
-
# Common Log Format:
|
19
|
+
# Common Log Format: https://httpd.apache.org/docs/2.4/logs.html#common
|
18
20
|
#
|
19
21
|
# lilith.local - - [07/Aug/2006 23:58:02 -0400] "GET / HTTP/1.1" 500 -
|
20
22
|
#
|
@@ -23,10 +25,17 @@ module Puma
|
|
23
25
|
|
24
26
|
HIJACK_FORMAT = %{%s - %s [%s] "%s %s%s %s" HIJACKED -1 %0.4f\n}
|
25
27
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
28
|
+
LOG_TIME_FORMAT = '%d/%b/%Y:%H:%M:%S %z'
|
29
|
+
|
30
|
+
CONTENT_LENGTH = 'Content-Length' # should be lower case from app,
|
31
|
+
# Util::HeaderHash allows mixed
|
32
|
+
HTTP_VERSION = Const::HTTP_VERSION
|
33
|
+
HTTP_X_FORWARDED_FOR = Const::HTTP_X_FORWARDED_FOR
|
34
|
+
PATH_INFO = Const::PATH_INFO
|
35
|
+
QUERY_STRING = Const::QUERY_STRING
|
36
|
+
REMOTE_ADDR = Const::REMOTE_ADDR
|
37
|
+
REMOTE_USER = 'REMOTE_USER'
|
38
|
+
REQUEST_METHOD = Const::REQUEST_METHOD
|
30
39
|
|
31
40
|
def initialize(app, logger=nil)
|
32
41
|
@app = app
|
@@ -55,13 +64,13 @@ module Puma
|
|
55
64
|
now = Time.now
|
56
65
|
|
57
66
|
msg = HIJACK_FORMAT % [
|
58
|
-
env[
|
59
|
-
env[
|
60
|
-
now.strftime(
|
67
|
+
env[HTTP_X_FORWARDED_FOR] || env[REMOTE_ADDR] || "-",
|
68
|
+
env[REMOTE_USER] || "-",
|
69
|
+
now.strftime(LOG_TIME_FORMAT),
|
61
70
|
env[REQUEST_METHOD],
|
62
71
|
env[PATH_INFO],
|
63
72
|
env[QUERY_STRING].empty? ? "" : "?#{env[QUERY_STRING]}",
|
64
|
-
env[
|
73
|
+
env[HTTP_VERSION],
|
65
74
|
now - began_at ]
|
66
75
|
|
67
76
|
write(msg)
|
@@ -72,13 +81,13 @@ module Puma
|
|
72
81
|
length = extract_content_length(header)
|
73
82
|
|
74
83
|
msg = FORMAT % [
|
75
|
-
env[
|
76
|
-
env[
|
77
|
-
now.strftime(
|
84
|
+
env[HTTP_X_FORWARDED_FOR] || env[REMOTE_ADDR] || "-",
|
85
|
+
env[REMOTE_USER] || "-",
|
86
|
+
now.strftime(LOG_TIME_FORMAT),
|
78
87
|
env[REQUEST_METHOD],
|
79
88
|
env[PATH_INFO],
|
80
89
|
env[QUERY_STRING].empty? ? "" : "?#{env[QUERY_STRING]}",
|
81
|
-
env[
|
90
|
+
env[HTTP_VERSION],
|
82
91
|
status.to_s[0..3],
|
83
92
|
length,
|
84
93
|
now - began_at ]
|
data/lib/puma/configuration.rb
CHANGED
@@ -1,24 +1,16 @@
|
|
1
|
-
|
2
|
-
require 'puma/plugin'
|
3
|
-
require 'puma/const'
|
1
|
+
# frozen_string_literal: true
|
4
2
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
DefaultRackup = "config.ru"
|
9
|
-
|
10
|
-
DefaultTCPHost = "0.0.0.0"
|
11
|
-
DefaultTCPPort = 9292
|
12
|
-
DefaultWorkerTimeout = 60
|
13
|
-
DefaultWorkerShutdownTimeout = 30
|
14
|
-
end
|
3
|
+
require_relative 'plugin'
|
4
|
+
require_relative 'const'
|
5
|
+
require_relative 'dsl'
|
15
6
|
|
7
|
+
module Puma
|
16
8
|
# A class used for storing "leveled" configuration options.
|
17
9
|
#
|
18
10
|
# In this class any "user" specified options take precedence over any
|
19
11
|
# "file" specified options, take precedence over any "default" options.
|
20
12
|
#
|
21
|
-
# User input is
|
13
|
+
# User input is preferred over "defaults":
|
22
14
|
# user_options = { foo: "bar" }
|
23
15
|
# default_options = { foo: "zoo" }
|
24
16
|
# options = UserFileDefaultOptions.new(user_options, default_options)
|
@@ -30,7 +22,7 @@ module Puma
|
|
30
22
|
# puts options.all_of(:foo)
|
31
23
|
# # => ["bar", "zoo"]
|
32
24
|
#
|
33
|
-
# A "file" option can be set. This config will be
|
25
|
+
# A "file" option can be set. This config will be preferred over "default" options
|
34
26
|
# but will defer to any available "user" specified options.
|
35
27
|
#
|
36
28
|
# user_options = { foo: "bar" }
|
@@ -52,9 +44,7 @@ module Puma
|
|
52
44
|
attr_reader :user_options, :file_options, :default_options
|
53
45
|
|
54
46
|
def [](key)
|
55
|
-
|
56
|
-
return file_options[key] if file_options.key?(key)
|
57
|
-
return default_options[key] if default_options.key?(key)
|
47
|
+
fetch(key)
|
58
48
|
end
|
59
49
|
|
60
50
|
def []=(key, value)
|
@@ -62,7 +52,11 @@ module Puma
|
|
62
52
|
end
|
63
53
|
|
64
54
|
def fetch(key, default_value = nil)
|
65
|
-
|
55
|
+
return user_options[key] if user_options.key?(key)
|
56
|
+
return file_options[key] if file_options.key?(key)
|
57
|
+
return default_options[key] if default_options.key?(key)
|
58
|
+
|
59
|
+
default_value
|
66
60
|
end
|
67
61
|
|
68
62
|
def all_of(key)
|
@@ -88,6 +82,12 @@ module Puma
|
|
88
82
|
end
|
89
83
|
end
|
90
84
|
end
|
85
|
+
|
86
|
+
def final_options
|
87
|
+
default_options
|
88
|
+
.merge(file_options)
|
89
|
+
.merge(user_options)
|
90
|
+
end
|
91
91
|
end
|
92
92
|
|
93
93
|
# The main configuration class of Puma.
|
@@ -104,16 +104,17 @@ module Puma
|
|
104
104
|
#
|
105
105
|
# It also handles loading plugins.
|
106
106
|
#
|
107
|
-
#
|
107
|
+
# [Note:]
|
108
|
+
# `:port` and `:host` are not valid keys. By the time they make it to the
|
108
109
|
# configuration options they are expected to be incorporated into a `:binds` key.
|
109
110
|
# Under the hood the DSL maps `port` and `host` calls to `:binds`
|
110
111
|
#
|
111
|
-
#
|
112
|
-
#
|
113
|
-
#
|
114
|
-
#
|
115
|
-
#
|
116
|
-
#
|
112
|
+
# config = Configuration.new({}) do |user_config, file_config, default_config|
|
113
|
+
# user_config.port 3003
|
114
|
+
# end
|
115
|
+
# config.load
|
116
|
+
# puts config.options[:port]
|
117
|
+
# # => 3003
|
117
118
|
#
|
118
119
|
# It is expected that `load` is called on the configuration instance after setting
|
119
120
|
# config. This method expands any values in `config_file` and puts them into the
|
@@ -124,10 +125,56 @@ module Puma
|
|
124
125
|
# is done because an environment variable may have been modified while loading
|
125
126
|
# configuration files.
|
126
127
|
class Configuration
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
128
|
+
DEFAULTS = {
|
129
|
+
auto_trim_time: 30,
|
130
|
+
binds: ['tcp://0.0.0.0:9292'.freeze],
|
131
|
+
clean_thread_locals: false,
|
132
|
+
debug: false,
|
133
|
+
enable_keep_alives: true,
|
134
|
+
early_hints: nil,
|
135
|
+
environment: 'development'.freeze,
|
136
|
+
# Number of seconds to wait until we get the first data for the request.
|
137
|
+
first_data_timeout: 30,
|
138
|
+
# Number of seconds to wait until the next request before shutting down.
|
139
|
+
idle_timeout: nil,
|
140
|
+
io_selector_backend: :auto,
|
141
|
+
log_requests: false,
|
142
|
+
logger: STDOUT,
|
143
|
+
# How many requests to attempt inline before sending a client back to
|
144
|
+
# the reactor to be subject to normal ordering. The idea here is that
|
145
|
+
# we amortize the cost of going back to the reactor for a well behaved
|
146
|
+
# but very "greedy" client across 10 requests. This prevents a not
|
147
|
+
# well behaved client from monopolizing the thread forever.
|
148
|
+
max_fast_inline: 10,
|
149
|
+
max_threads: Puma.mri? ? 5 : 16,
|
150
|
+
min_threads: 0,
|
151
|
+
mode: :http,
|
152
|
+
mutate_stdout_and_stderr_to_sync_on_write: true,
|
153
|
+
out_of_band: [],
|
154
|
+
# Number of seconds for another request within a persistent session.
|
155
|
+
persistent_timeout: 20,
|
156
|
+
queue_requests: true,
|
157
|
+
rackup: 'config.ru'.freeze,
|
158
|
+
raise_exception_on_sigterm: true,
|
159
|
+
reaping_time: 1,
|
160
|
+
remote_address: :socket,
|
161
|
+
silence_single_worker_warning: false,
|
162
|
+
silence_fork_callback_warning: false,
|
163
|
+
tag: File.basename(Dir.getwd),
|
164
|
+
tcp_host: '0.0.0.0'.freeze,
|
165
|
+
tcp_port: 9292,
|
166
|
+
wait_for_less_busy_worker: 0.005,
|
167
|
+
worker_boot_timeout: 60,
|
168
|
+
worker_check_interval: 5,
|
169
|
+
worker_culling_strategy: :youngest,
|
170
|
+
worker_shutdown_timeout: 30,
|
171
|
+
worker_timeout: 60,
|
172
|
+
workers: 0,
|
173
|
+
http_content_length_limit: nil
|
174
|
+
}
|
175
|
+
|
176
|
+
def initialize(user_options={}, default_options = {}, env = ENV, &block)
|
177
|
+
default_options = self.puma_default_options(env).merge(default_options)
|
131
178
|
|
132
179
|
@options = UserFileDefaultOptions.new(user_options, default_options)
|
133
180
|
@plugins = PluginLoader.new
|
@@ -135,6 +182,12 @@ module Puma
|
|
135
182
|
@file_dsl = DSL.new(@options.file_options, self)
|
136
183
|
@default_dsl = DSL.new(@options.default_options, self)
|
137
184
|
|
185
|
+
if !@options[:prune_bundler]
|
186
|
+
default_options[:preload_app] = (@options[:workers] > 1) && Puma.forkable?
|
187
|
+
end
|
188
|
+
|
189
|
+
@puma_bundler_pruned = env.key? 'PUMA_BUNDLER_PRUNED'
|
190
|
+
|
138
191
|
if block
|
139
192
|
configure(&block)
|
140
193
|
end
|
@@ -165,26 +218,27 @@ module Puma
|
|
165
218
|
self
|
166
219
|
end
|
167
220
|
|
168
|
-
def puma_default_options
|
221
|
+
def puma_default_options(env = ENV)
|
222
|
+
defaults = DEFAULTS.dup
|
223
|
+
puma_options_from_env(env).each { |k,v| defaults[k] = v if v }
|
224
|
+
defaults
|
225
|
+
end
|
226
|
+
|
227
|
+
def puma_options_from_env(env = ENV)
|
228
|
+
min = env['PUMA_MIN_THREADS'] || env['MIN_THREADS']
|
229
|
+
max = env['PUMA_MAX_THREADS'] || env['MAX_THREADS']
|
230
|
+
workers = if env['WEB_CONCURRENCY'] == 'auto'
|
231
|
+
require_processor_counter
|
232
|
+
::Concurrent.available_processor_count
|
233
|
+
else
|
234
|
+
env['WEB_CONCURRENCY']
|
235
|
+
end
|
236
|
+
|
169
237
|
{
|
170
|
-
:
|
171
|
-
:
|
172
|
-
:
|
173
|
-
:
|
174
|
-
:binds => ["tcp://#{DefaultTCPHost}:#{DefaultTCPPort}"],
|
175
|
-
:workers => 0,
|
176
|
-
:daemon => false,
|
177
|
-
:mode => :http,
|
178
|
-
:worker_timeout => DefaultWorkerTimeout,
|
179
|
-
:worker_boot_timeout => DefaultWorkerTimeout,
|
180
|
-
:worker_shutdown_timeout => DefaultWorkerShutdownTimeout,
|
181
|
-
:remote_address => :socket,
|
182
|
-
:tag => method(:infer_tag),
|
183
|
-
:environment => -> { ENV['RACK_ENV'] || "development" },
|
184
|
-
:rackup => DefaultRackup,
|
185
|
-
:logger => STDOUT,
|
186
|
-
:persistent_timeout => Const::PERSISTENT_TIMEOUT,
|
187
|
-
:first_data_timeout => Const::FIRST_DATA_TIMEOUT
|
238
|
+
min_threads: min && min != "" && Integer(min),
|
239
|
+
max_threads: max && max != "" && Integer(max),
|
240
|
+
workers: workers && workers != "" && Integer(workers),
|
241
|
+
environment: env['APP_ENV'] || env['RACK_ENV'] || env['RAILS_ENV'],
|
188
242
|
}
|
189
243
|
end
|
190
244
|
|
@@ -200,7 +254,7 @@ module Puma
|
|
200
254
|
return [] if files == ['-']
|
201
255
|
return files if files.any?
|
202
256
|
|
203
|
-
first_default_file = %W(config/puma/#{
|
257
|
+
first_default_file = %W(config/puma/#{@options[:environment]}.rb config/puma.rb).find do |f|
|
204
258
|
File.exist?(f)
|
205
259
|
end
|
206
260
|
|
@@ -242,16 +296,8 @@ module Puma
|
|
242
296
|
def app
|
243
297
|
found = options[:app] || load_rackup
|
244
298
|
|
245
|
-
if @options[:mode] == :tcp
|
246
|
-
require 'puma/tcp_logger'
|
247
|
-
|
248
|
-
logger = @options[:logger]
|
249
|
-
quiet = !@options[:log_requests]
|
250
|
-
return TCPLogger.new(logger, found, quiet)
|
251
|
-
end
|
252
|
-
|
253
299
|
if @options[:log_requests]
|
254
|
-
|
300
|
+
require_relative 'commonlogger'
|
255
301
|
logger = @options[:logger]
|
256
302
|
found = CommonLogger.new(found, logger)
|
257
303
|
end
|
@@ -264,16 +310,33 @@ module Puma
|
|
264
310
|
@options[:environment]
|
265
311
|
end
|
266
312
|
|
267
|
-
def environment_str
|
268
|
-
environment.respond_to?(:call) ? environment.call : environment
|
269
|
-
end
|
270
|
-
|
271
313
|
def load_plugin(name)
|
272
314
|
@plugins.create name
|
273
315
|
end
|
274
316
|
|
275
|
-
|
276
|
-
|
317
|
+
# @param key [:Symbol] hook to run
|
318
|
+
# @param arg [Launcher, Int] `:on_restart` passes Launcher
|
319
|
+
#
|
320
|
+
def run_hooks(key, arg, log_writer, hook_data = nil)
|
321
|
+
log_writer.debug "Running #{key} hooks"
|
322
|
+
|
323
|
+
@options.all_of(key).each do |b|
|
324
|
+
begin
|
325
|
+
if Array === b
|
326
|
+
hook_data[b[1]] ||= Hash.new
|
327
|
+
b[0].call arg, hook_data[b[1]]
|
328
|
+
else
|
329
|
+
b.call arg
|
330
|
+
end
|
331
|
+
rescue => e
|
332
|
+
log_writer.log "WARNING hook #{key} failed with exception (#{e.class}) #{e.message}"
|
333
|
+
log_writer.debug e.backtrace.join("\n")
|
334
|
+
end
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
338
|
+
def final_options
|
339
|
+
@options.final_options
|
277
340
|
end
|
278
341
|
|
279
342
|
def self.temp_path
|
@@ -285,8 +348,14 @@ module Puma
|
|
285
348
|
|
286
349
|
private
|
287
350
|
|
288
|
-
def
|
289
|
-
|
351
|
+
def require_processor_counter
|
352
|
+
require 'concurrent/utility/processor_counter'
|
353
|
+
rescue LoadError
|
354
|
+
warn <<~MESSAGE
|
355
|
+
WEB_CONCURRENCY=auto requires the "concurrent-ruby" gem to be installed.
|
356
|
+
Please add "concurrent-ruby" to your Gemfile.
|
357
|
+
MESSAGE
|
358
|
+
raise
|
290
359
|
end
|
291
360
|
|
292
361
|
# Load and use the normal Rack builder if we can, otherwise
|
@@ -294,7 +363,7 @@ module Puma
|
|
294
363
|
def rack_builder
|
295
364
|
# Load bundler now if we can so that we can pickup rack from
|
296
365
|
# a Gemfile
|
297
|
-
if
|
366
|
+
if @puma_bundler_pruned
|
298
367
|
begin
|
299
368
|
require 'bundler/setup'
|
300
369
|
rescue LoadError
|
@@ -304,11 +373,10 @@ module Puma
|
|
304
373
|
begin
|
305
374
|
require 'rack'
|
306
375
|
require 'rack/builder'
|
376
|
+
::Rack::Builder
|
307
377
|
rescue LoadError
|
308
|
-
|
309
|
-
|
310
|
-
else
|
311
|
-
return ::Rack::Builder
|
378
|
+
require_relative 'rack/builder'
|
379
|
+
Puma::Rack::Builder
|
312
380
|
end
|
313
381
|
end
|
314
382
|
|
@@ -316,6 +384,8 @@ module Puma
|
|
316
384
|
raise "Missing rackup file '#{rackup}'" unless File.exist?(rackup)
|
317
385
|
|
318
386
|
rack_app, rack_options = rack_builder.parse_file(rackup)
|
387
|
+
rack_options = rack_options || {}
|
388
|
+
|
319
389
|
@options.file_options.merge!(rack_options)
|
320
390
|
|
321
391
|
config_ru_binds = []
|
@@ -329,31 +399,9 @@ module Puma
|
|
329
399
|
end
|
330
400
|
|
331
401
|
def self.random_token
|
332
|
-
|
333
|
-
require 'openssl'
|
334
|
-
rescue LoadError
|
335
|
-
end
|
336
|
-
|
337
|
-
count = 16
|
338
|
-
|
339
|
-
bytes = nil
|
402
|
+
require 'securerandom' unless defined?(SecureRandom)
|
340
403
|
|
341
|
-
|
342
|
-
bytes = OpenSSL::Random.random_bytes(count)
|
343
|
-
elsif File.exist?("/dev/urandom")
|
344
|
-
File.open('/dev/urandom') { |f| bytes = f.read(count) }
|
345
|
-
end
|
346
|
-
|
347
|
-
if bytes
|
348
|
-
token = "".dup
|
349
|
-
bytes.each_byte { |b| token << b.to_s(16) }
|
350
|
-
else
|
351
|
-
token = (0..count).to_a.map { rand(255).to_s(16) }.join
|
352
|
-
end
|
353
|
-
|
354
|
-
return token
|
404
|
+
SecureRandom.hex(16)
|
355
405
|
end
|
356
406
|
end
|
357
407
|
end
|
358
|
-
|
359
|
-
require 'puma/dsl'
|