puma 5.6.4 → 6.0.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 +163 -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/nginx.md +1 -1
- 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 +26 -13
- data/lib/puma/cluster/worker.rb +13 -11
- data/lib/puma/cluster/worker_handle.rb +4 -1
- data/lib/puma/cluster.rb +31 -30
- data/lib/puma/configuration.rb +74 -58
- data/lib/puma/const.rb +76 -88
- data/lib/puma/control_cli.rb +21 -18
- data/lib/puma/detect.rb +2 -0
- data/lib/puma/dsl.rb +97 -49
- data/lib/puma/error_logger.rb +17 -9
- data/lib/puma/events.rb +6 -126
- data/lib/puma/io_buffer.rb +39 -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/rack/builder.rb +4 -4
- data/lib/puma/rack_default.rb +1 -1
- data/lib/puma/reactor.rb +4 -4
- data/lib/puma/request.rb +334 -162
- data/lib/puma/runner.rb +45 -20
- data/lib/puma/server.rb +55 -69
- data/lib/puma/single.rb +11 -11
- data/lib/puma/state_file.rb +2 -4
- data/lib/puma/systemd.rb +3 -2
- data/lib/puma/thread_pool.rb +16 -16
- data/lib/puma/util.rb +12 -14
- data/lib/puma.rb +12 -11
- data/lib/rack/handler/puma.rb +9 -9
- metadata +7 -3
- data/lib/puma/queue_close.rb +0 -26
data/lib/puma/cluster.rb
CHANGED
@@ -1,12 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
require 'time'
|
3
|
+
require_relative 'runner'
|
4
|
+
require_relative 'util'
|
5
|
+
require_relative 'plugin'
|
6
|
+
require_relative 'cluster/worker_handle'
|
7
|
+
require_relative 'cluster/worker'
|
10
8
|
|
11
9
|
module Puma
|
12
10
|
# This class is instantiated by the `Puma::Launcher` and used
|
@@ -17,8 +15,8 @@ module Puma
|
|
17
15
|
# via the `spawn_workers` method call. Each worker will have it's own
|
18
16
|
# instance of a `Puma::Server`.
|
19
17
|
class Cluster < Runner
|
20
|
-
def initialize(
|
21
|
-
super
|
18
|
+
def initialize(launcher)
|
19
|
+
super(launcher)
|
22
20
|
|
23
21
|
@phase = 0
|
24
22
|
@workers = []
|
@@ -27,6 +25,10 @@ module Puma
|
|
27
25
|
@phased_restart = false
|
28
26
|
end
|
29
27
|
|
28
|
+
# Returns the list of cluster worker handles.
|
29
|
+
# @return [Array<Puma::Cluster::WorkerHandle>]
|
30
|
+
attr_reader :workers
|
31
|
+
|
30
32
|
def stop_workers
|
31
33
|
log "- Gracefully shutting down workers..."
|
32
34
|
@workers.each { |x| x.term }
|
@@ -92,7 +94,7 @@ module Puma
|
|
92
94
|
|
93
95
|
# @version 5.0.0
|
94
96
|
def spawn_worker(idx, master)
|
95
|
-
@
|
97
|
+
@config.run_hooks(:before_worker_fork, idx, @log_writer)
|
96
98
|
|
97
99
|
pid = fork { worker(idx, master) }
|
98
100
|
if !pid
|
@@ -101,7 +103,7 @@ module Puma
|
|
101
103
|
exit! 1
|
102
104
|
end
|
103
105
|
|
104
|
-
@
|
106
|
+
@config.run_hooks(:after_worker_fork, idx, @log_writer)
|
105
107
|
pid
|
106
108
|
end
|
107
109
|
|
@@ -176,10 +178,10 @@ module Puma
|
|
176
178
|
end
|
177
179
|
end
|
178
180
|
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
].compact.min
|
181
|
+
t = @workers.reject(&:term?)
|
182
|
+
t.map!(&:ping_timeout)
|
183
|
+
|
184
|
+
@next_check = [t.min, @next_check].compact.min
|
183
185
|
end
|
184
186
|
|
185
187
|
def worker(index, master)
|
@@ -209,8 +211,8 @@ module Puma
|
|
209
211
|
stop
|
210
212
|
end
|
211
213
|
|
212
|
-
def phased_restart
|
213
|
-
return false if @options[:preload_app]
|
214
|
+
def phased_restart(refork = false)
|
215
|
+
return false if @options[:preload_app] && !refork
|
214
216
|
|
215
217
|
@phased_restart = true
|
216
218
|
wakeup!
|
@@ -226,7 +228,7 @@ module Puma
|
|
226
228
|
def stop_blocked
|
227
229
|
@status = :stop if @status == :run
|
228
230
|
wakeup!
|
229
|
-
@control
|
231
|
+
@control&.stop true
|
230
232
|
Process.waitall
|
231
233
|
end
|
232
234
|
|
@@ -248,24 +250,24 @@ module Puma
|
|
248
250
|
old_worker_count = @workers.count { |w| w.phase != @phase }
|
249
251
|
worker_status = @workers.map do |w|
|
250
252
|
{
|
251
|
-
started_at: w.started_at
|
253
|
+
started_at: utc_iso8601(w.started_at),
|
252
254
|
pid: w.pid,
|
253
255
|
index: w.index,
|
254
256
|
phase: w.phase,
|
255
257
|
booted: w.booted?,
|
256
|
-
last_checkin: w.last_checkin
|
258
|
+
last_checkin: utc_iso8601(w.last_checkin),
|
257
259
|
last_status: w.last_status,
|
258
260
|
}
|
259
261
|
end
|
260
262
|
|
261
263
|
{
|
262
|
-
started_at: @started_at
|
264
|
+
started_at: utc_iso8601(@started_at),
|
263
265
|
workers: @workers.size,
|
264
266
|
phase: @phase,
|
265
267
|
booted_workers: worker_status.count { |w| w[:booted] },
|
266
268
|
old_workers: old_worker_count,
|
267
269
|
worker_status: worker_status,
|
268
|
-
}
|
270
|
+
}.merge(super)
|
269
271
|
end
|
270
272
|
|
271
273
|
def preload?
|
@@ -277,7 +279,7 @@ module Puma
|
|
277
279
|
if (worker = @workers.find { |w| w.index == 0 })
|
278
280
|
worker.phase += 1
|
279
281
|
end
|
280
|
-
phased_restart
|
282
|
+
phased_restart(true)
|
281
283
|
end
|
282
284
|
|
283
285
|
# We do this in a separate method to keep the lambda scope
|
@@ -290,7 +292,7 @@ module Puma
|
|
290
292
|
|
291
293
|
# Auto-fork after the specified number of requests.
|
292
294
|
if (fork_requests = @options[:fork_worker].to_i) > 0
|
293
|
-
@
|
295
|
+
@events.register(:ping!) do |w|
|
294
296
|
fork_worker! if w.index == 0 &&
|
295
297
|
w.phase == 0 &&
|
296
298
|
w.last_status[:requests_count] >= fork_requests
|
@@ -372,12 +374,12 @@ module Puma
|
|
372
374
|
else
|
373
375
|
log "* Restarts: (\u2714) hot (\u2714) phased"
|
374
376
|
|
375
|
-
unless @
|
377
|
+
unless @config.app_configured?
|
376
378
|
error "No application configured, nothing to run"
|
377
379
|
exit 1
|
378
380
|
end
|
379
381
|
|
380
|
-
@launcher.binder.parse @options[:binds]
|
382
|
+
@launcher.binder.parse @options[:binds]
|
381
383
|
end
|
382
384
|
|
383
385
|
read, @wakeup = Puma::Util.pipe
|
@@ -409,8 +411,7 @@ module Puma
|
|
409
411
|
|
410
412
|
@master_read, @worker_write = read, @wakeup
|
411
413
|
|
412
|
-
@
|
413
|
-
Puma::Util.nakayoshi_gc @events if @options[:nakayoshi_fork]
|
414
|
+
@config.run_hooks(:before_fork, nil, @log_writer)
|
414
415
|
|
415
416
|
spawn_workers
|
416
417
|
|
@@ -463,9 +464,9 @@ module Puma
|
|
463
464
|
w.term unless w.term?
|
464
465
|
when "p"
|
465
466
|
w.ping!(result.sub(/^\d+/,'').chomp)
|
466
|
-
@
|
467
|
+
@events.fire(:ping!, w)
|
467
468
|
if !booted && @workers.none? {|worker| worker.last_status.empty?}
|
468
|
-
@
|
469
|
+
@events.fire_on_booted!
|
469
470
|
booted = true
|
470
471
|
end
|
471
472
|
end
|
data/lib/puma/configuration.rb
CHANGED
@@ -1,21 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
require_relative 'rack/builder'
|
4
|
+
require_relative 'plugin'
|
5
|
+
require_relative 'const'
|
6
|
+
# note that dsl is loaded at end of file, requires ConfigDefault constants
|
6
7
|
|
7
8
|
module Puma
|
8
|
-
|
9
|
-
module ConfigDefault
|
10
|
-
DefaultRackup = "config.ru"
|
11
|
-
|
12
|
-
DefaultTCPHost = "0.0.0.0"
|
13
|
-
DefaultTCPPort = 9292
|
14
|
-
DefaultWorkerCheckInterval = 5
|
15
|
-
DefaultWorkerTimeout = 60
|
16
|
-
DefaultWorkerShutdownTimeout = 30
|
17
|
-
end
|
18
|
-
|
19
9
|
# A class used for storing "leveled" configuration options.
|
20
10
|
#
|
21
11
|
# In this class any "user" specified options take precedence over any
|
@@ -136,7 +126,48 @@ module Puma
|
|
136
126
|
# is done because an environment variable may have been modified while loading
|
137
127
|
# configuration files.
|
138
128
|
class Configuration
|
139
|
-
|
129
|
+
DEFAULTS = {
|
130
|
+
auto_trim_time: 30,
|
131
|
+
binds: ['tcp://0.0.0.0:9292'.freeze],
|
132
|
+
clean_thread_locals: false,
|
133
|
+
debug: false,
|
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
|
+
io_selector_backend: :auto,
|
139
|
+
log_requests: false,
|
140
|
+
logger: STDOUT,
|
141
|
+
# How many requests to attempt inline before sending a client back to
|
142
|
+
# the reactor to be subject to normal ordering. The idea here is that
|
143
|
+
# we amortize the cost of going back to the reactor for a well behaved
|
144
|
+
# but very "greedy" client across 10 requests. This prevents a not
|
145
|
+
# well behaved client from monopolizing the thread forever.
|
146
|
+
max_fast_inline: 10,
|
147
|
+
max_threads: Puma.mri? ? 5 : 16,
|
148
|
+
min_threads: 0,
|
149
|
+
mode: :http,
|
150
|
+
mutate_stdout_and_stderr_to_sync_on_write: true,
|
151
|
+
out_of_band: [],
|
152
|
+
# Number of seconds for another request within a persistent session.
|
153
|
+
persistent_timeout: 20,
|
154
|
+
queue_requests: true,
|
155
|
+
rackup: 'config.ru'.freeze,
|
156
|
+
raise_exception_on_sigterm: true,
|
157
|
+
reaping_time: 1,
|
158
|
+
remote_address: :socket,
|
159
|
+
silence_single_worker_warning: false,
|
160
|
+
tag: File.basename(Dir.getwd),
|
161
|
+
tcp_host: '0.0.0.0'.freeze,
|
162
|
+
tcp_port: 9292,
|
163
|
+
wait_for_less_busy_worker: 0.005,
|
164
|
+
worker_boot_timeout: 60,
|
165
|
+
worker_check_interval: 5,
|
166
|
+
worker_culling_strategy: :youngest,
|
167
|
+
worker_shutdown_timeout: 30,
|
168
|
+
worker_timeout: 60,
|
169
|
+
workers: 0,
|
170
|
+
}
|
140
171
|
|
141
172
|
def initialize(user_options={}, default_options = {}, &block)
|
142
173
|
default_options = self.puma_default_options.merge(default_options)
|
@@ -181,37 +212,22 @@ module Puma
|
|
181
212
|
self
|
182
213
|
end
|
183
214
|
|
184
|
-
|
185
|
-
|
186
|
-
|
215
|
+
def puma_default_options
|
216
|
+
defaults = DEFAULTS.dup
|
217
|
+
puma_options_from_env.each { |k,v| defaults[k] = v if v }
|
218
|
+
defaults
|
187
219
|
end
|
188
220
|
|
189
|
-
def
|
221
|
+
def puma_options_from_env
|
222
|
+
min = ENV['PUMA_MIN_THREADS'] || ENV['MIN_THREADS']
|
223
|
+
max = ENV['PUMA_MAX_THREADS'] || ENV['MAX_THREADS']
|
224
|
+
workers = ENV['WEB_CONCURRENCY']
|
225
|
+
|
190
226
|
{
|
191
|
-
:
|
192
|
-
:
|
193
|
-
:
|
194
|
-
:
|
195
|
-
:binds => ["tcp://#{DefaultTCPHost}:#{DefaultTCPPort}"],
|
196
|
-
:workers => Integer(ENV['WEB_CONCURRENCY'] || 0),
|
197
|
-
:silence_single_worker_warning => false,
|
198
|
-
:mode => :http,
|
199
|
-
:worker_check_interval => DefaultWorkerCheckInterval,
|
200
|
-
:worker_timeout => DefaultWorkerTimeout,
|
201
|
-
:worker_boot_timeout => DefaultWorkerTimeout,
|
202
|
-
:worker_shutdown_timeout => DefaultWorkerShutdownTimeout,
|
203
|
-
:worker_culling_strategy => :youngest,
|
204
|
-
:remote_address => :socket,
|
205
|
-
:tag => method(:infer_tag),
|
206
|
-
:environment => -> { ENV['APP_ENV'] || ENV['RACK_ENV'] || ENV['RAILS_ENV'] || 'development' },
|
207
|
-
:rackup => DefaultRackup,
|
208
|
-
:logger => STDOUT,
|
209
|
-
:persistent_timeout => Const::PERSISTENT_TIMEOUT,
|
210
|
-
:first_data_timeout => Const::FIRST_DATA_TIMEOUT,
|
211
|
-
:raise_exception_on_sigterm => true,
|
212
|
-
:max_fast_inline => Const::MAX_FAST_INLINE,
|
213
|
-
:io_selector_backend => :auto,
|
214
|
-
:mutate_stdout_and_stderr_to_sync_on_write => true,
|
227
|
+
min_threads: min && Integer(min),
|
228
|
+
max_threads: max && Integer(max),
|
229
|
+
workers: workers && Integer(workers),
|
230
|
+
environment: ENV['APP_ENV'] || ENV['RACK_ENV'] || ENV['RAILS_ENV'],
|
215
231
|
}
|
216
232
|
end
|
217
233
|
|
@@ -227,7 +243,7 @@ module Puma
|
|
227
243
|
return [] if files == ['-']
|
228
244
|
return files if files.any?
|
229
245
|
|
230
|
-
first_default_file = %W(config/puma/#{
|
246
|
+
first_default_file = %W(config/puma/#{@options[:environment]}.rb config/puma.rb).find do |f|
|
231
247
|
File.exist?(f)
|
232
248
|
end
|
233
249
|
|
@@ -270,7 +286,7 @@ module Puma
|
|
270
286
|
found = options[:app] || load_rackup
|
271
287
|
|
272
288
|
if @options[:log_requests]
|
273
|
-
|
289
|
+
require_relative 'commonlogger'
|
274
290
|
logger = @options[:logger]
|
275
291
|
found = CommonLogger.new(found, logger)
|
276
292
|
end
|
@@ -283,21 +299,25 @@ module Puma
|
|
283
299
|
@options[:environment]
|
284
300
|
end
|
285
301
|
|
286
|
-
def environment_str
|
287
|
-
environment.respond_to?(:call) ? environment.call : environment
|
288
|
-
end
|
289
|
-
|
290
302
|
def load_plugin(name)
|
291
303
|
@plugins.create name
|
292
304
|
end
|
293
305
|
|
294
|
-
|
306
|
+
# @param key [:Symbol] hook to run
|
307
|
+
# @param arg [Launcher, Int] `:on_restart` passes Launcher
|
308
|
+
#
|
309
|
+
def run_hooks(key, arg, log_writer, hook_data = nil)
|
295
310
|
@options.all_of(key).each do |b|
|
296
311
|
begin
|
297
|
-
b
|
312
|
+
if Array === b
|
313
|
+
hook_data[b[1]] ||= Hash.new
|
314
|
+
b[0].call arg, hook_data[b[1]]
|
315
|
+
else
|
316
|
+
b.call arg
|
317
|
+
end
|
298
318
|
rescue => e
|
299
|
-
|
300
|
-
|
319
|
+
log_writer.log "WARNING hook #{key} failed with exception (#{e.class}) #{e.message}"
|
320
|
+
log_writer.debug e.backtrace.join("\n")
|
301
321
|
end
|
302
322
|
end
|
303
323
|
end
|
@@ -315,10 +335,6 @@ module Puma
|
|
315
335
|
|
316
336
|
private
|
317
337
|
|
318
|
-
def infer_tag
|
319
|
-
File.basename(Dir.getwd)
|
320
|
-
end
|
321
|
-
|
322
338
|
# Load and use the normal Rack builder if we can, otherwise
|
323
339
|
# fallback to our minimal version.
|
324
340
|
def rack_builder
|
@@ -368,4 +384,4 @@ module Puma
|
|
368
384
|
end
|
369
385
|
end
|
370
386
|
|
371
|
-
|
387
|
+
require_relative 'dsl'
|
data/lib/puma/const.rb
CHANGED
@@ -5,7 +5,6 @@ module Puma
|
|
5
5
|
class UnsupportedOption < RuntimeError
|
6
6
|
end
|
7
7
|
|
8
|
-
|
9
8
|
# Every standard HTTP code mapped to the appropriate message. These are
|
10
9
|
# used so frequently that they are placed directly in Puma for easy
|
11
10
|
# access rather than Puma::Const itself.
|
@@ -100,55 +99,40 @@ module Puma
|
|
100
99
|
# too taxing on performance.
|
101
100
|
module Const
|
102
101
|
|
103
|
-
PUMA_VERSION = VERSION = "
|
104
|
-
CODE_NAME = "
|
102
|
+
PUMA_VERSION = VERSION = "6.0.2"
|
103
|
+
CODE_NAME = "Sunflower"
|
105
104
|
|
106
|
-
PUMA_SERVER_STRING = [
|
105
|
+
PUMA_SERVER_STRING = ["puma", PUMA_VERSION, CODE_NAME].join(" ").freeze
|
107
106
|
|
108
107
|
FAST_TRACK_KA_TIMEOUT = 0.2
|
109
108
|
|
110
|
-
# The default number of seconds for another request within a persistent
|
111
|
-
# session.
|
112
|
-
PERSISTENT_TIMEOUT = 20
|
113
|
-
|
114
|
-
# The default number of seconds to wait until we get the first data
|
115
|
-
# for the request
|
116
|
-
FIRST_DATA_TIMEOUT = 30
|
117
|
-
|
118
109
|
# How long to wait when getting some write blocking on the socket when
|
119
110
|
# sending data back
|
120
111
|
WRITE_TIMEOUT = 10
|
121
112
|
|
122
|
-
# How many requests to attempt inline before sending a client back to
|
123
|
-
# the reactor to be subject to normal ordering. The idea here is that
|
124
|
-
# we amortize the cost of going back to the reactor for a well behaved
|
125
|
-
# but very "greedy" client across 10 requests. This prevents a not
|
126
|
-
# well behaved client from monopolizing the thread forever.
|
127
|
-
MAX_FAST_INLINE = 10
|
128
|
-
|
129
113
|
# The original URI requested by the client.
|
130
|
-
REQUEST_URI=
|
131
|
-
REQUEST_PATH =
|
132
|
-
QUERY_STRING =
|
133
|
-
CONTENT_LENGTH = "CONTENT_LENGTH"
|
114
|
+
REQUEST_URI= "REQUEST_URI"
|
115
|
+
REQUEST_PATH = "REQUEST_PATH"
|
116
|
+
QUERY_STRING = "QUERY_STRING"
|
117
|
+
CONTENT_LENGTH = "CONTENT_LENGTH"
|
134
118
|
|
135
|
-
PATH_INFO =
|
119
|
+
PATH_INFO = "PATH_INFO"
|
136
120
|
|
137
|
-
PUMA_TMP_BASE = "puma"
|
121
|
+
PUMA_TMP_BASE = "puma"
|
138
122
|
|
139
123
|
ERROR_RESPONSE = {
|
140
124
|
# Indicate that we couldn't parse the request
|
141
|
-
400 => "HTTP/1.1 400 Bad Request\r\n\r\n"
|
125
|
+
400 => "HTTP/1.1 400 Bad Request\r\n\r\n",
|
142
126
|
# The standard empty 404 response for bad requests. Use Error4040Handler for custom stuff.
|
143
|
-
404 => "HTTP/1.1 404 Not Found\r\nConnection: close\r\nServer: Puma #{PUMA_VERSION}\r\n\r\nNOT FOUND"
|
127
|
+
404 => "HTTP/1.1 404 Not Found\r\nConnection: close\r\nServer: Puma #{PUMA_VERSION}\r\n\r\nNOT FOUND",
|
144
128
|
# The standard empty 408 response for requests that timed out.
|
145
|
-
408 => "HTTP/1.1 408 Request Timeout\r\nConnection: close\r\nServer: Puma #{PUMA_VERSION}\r\n\r\n"
|
129
|
+
408 => "HTTP/1.1 408 Request Timeout\r\nConnection: close\r\nServer: Puma #{PUMA_VERSION}\r\n\r\n",
|
146
130
|
# Indicate that there was an internal error, obviously.
|
147
|
-
500 => "HTTP/1.1 500 Internal Server Error\r\n\r\n"
|
131
|
+
500 => "HTTP/1.1 500 Internal Server Error\r\n\r\n",
|
148
132
|
# Incorrect or invalid header value
|
149
|
-
501 => "HTTP/1.1 501 Not Implemented\r\n\r\n"
|
133
|
+
501 => "HTTP/1.1 501 Not Implemented\r\n\r\n",
|
150
134
|
# A common header for indicating the server is too busy. Not used yet.
|
151
|
-
503 => "HTTP/1.1 503 Service Unavailable\r\n\r\nBUSY"
|
135
|
+
503 => "HTTP/1.1 503 Service Unavailable\r\n\r\nBUSY"
|
152
136
|
}.freeze
|
153
137
|
|
154
138
|
# The basic max request size we'll try to read.
|
@@ -161,84 +145,88 @@ module Puma
|
|
161
145
|
# Maximum request body size before it is moved out of memory and into a tempfile for reading.
|
162
146
|
MAX_BODY = MAX_HEADER
|
163
147
|
|
164
|
-
REQUEST_METHOD = "REQUEST_METHOD"
|
165
|
-
HEAD = "HEAD"
|
148
|
+
REQUEST_METHOD = "REQUEST_METHOD"
|
149
|
+
HEAD = "HEAD"
|
150
|
+
SUPPORTED_HTTP_METHODS = %w[HEAD GET POST PUT DELETE OPTIONS TRACE PATCH].freeze
|
166
151
|
# ETag is based on the apache standard of hex mtime-size-inode (inode is 0 on win32)
|
167
|
-
LINE_END = "\r\n"
|
168
|
-
REMOTE_ADDR = "REMOTE_ADDR"
|
169
|
-
HTTP_X_FORWARDED_FOR = "HTTP_X_FORWARDED_FOR"
|
170
|
-
HTTP_X_FORWARDED_SSL = "HTTP_X_FORWARDED_SSL"
|
171
|
-
HTTP_X_FORWARDED_SCHEME = "HTTP_X_FORWARDED_SCHEME"
|
172
|
-
HTTP_X_FORWARDED_PROTO = "HTTP_X_FORWARDED_PROTO"
|
152
|
+
LINE_END = "\r\n"
|
153
|
+
REMOTE_ADDR = "REMOTE_ADDR"
|
154
|
+
HTTP_X_FORWARDED_FOR = "HTTP_X_FORWARDED_FOR"
|
155
|
+
HTTP_X_FORWARDED_SSL = "HTTP_X_FORWARDED_SSL"
|
156
|
+
HTTP_X_FORWARDED_SCHEME = "HTTP_X_FORWARDED_SCHEME"
|
157
|
+
HTTP_X_FORWARDED_PROTO = "HTTP_X_FORWARDED_PROTO"
|
173
158
|
|
174
|
-
SERVER_NAME = "SERVER_NAME"
|
175
|
-
SERVER_PORT = "SERVER_PORT"
|
176
|
-
HTTP_HOST = "HTTP_HOST"
|
177
|
-
PORT_80 = "80"
|
178
|
-
PORT_443 = "443"
|
179
|
-
LOCALHOST = "localhost"
|
180
|
-
|
159
|
+
SERVER_NAME = "SERVER_NAME"
|
160
|
+
SERVER_PORT = "SERVER_PORT"
|
161
|
+
HTTP_HOST = "HTTP_HOST"
|
162
|
+
PORT_80 = "80"
|
163
|
+
PORT_443 = "443"
|
164
|
+
LOCALHOST = "localhost"
|
165
|
+
LOCALHOST_IPV4 = "127.0.0.1"
|
166
|
+
LOCALHOST_IPV6 = "::1"
|
167
|
+
UNSPECIFIED_IPV4 = "0.0.0.0"
|
168
|
+
UNSPECIFIED_IPV6 = "::"
|
181
169
|
|
182
|
-
SERVER_PROTOCOL = "SERVER_PROTOCOL"
|
183
|
-
HTTP_11 = "HTTP/1.1"
|
170
|
+
SERVER_PROTOCOL = "SERVER_PROTOCOL"
|
171
|
+
HTTP_11 = "HTTP/1.1"
|
184
172
|
|
185
|
-
SERVER_SOFTWARE = "SERVER_SOFTWARE"
|
186
|
-
GATEWAY_INTERFACE = "GATEWAY_INTERFACE"
|
187
|
-
CGI_VER = "CGI/1.2"
|
173
|
+
SERVER_SOFTWARE = "SERVER_SOFTWARE"
|
174
|
+
GATEWAY_INTERFACE = "GATEWAY_INTERFACE"
|
175
|
+
CGI_VER = "CGI/1.2"
|
188
176
|
|
189
|
-
STOP_COMMAND = "?"
|
190
|
-
HALT_COMMAND = "!"
|
191
|
-
RESTART_COMMAND = "R"
|
177
|
+
STOP_COMMAND = "?"
|
178
|
+
HALT_COMMAND = "!"
|
179
|
+
RESTART_COMMAND = "R"
|
192
180
|
|
193
|
-
RACK_INPUT = "rack.input"
|
194
|
-
RACK_URL_SCHEME = "rack.url_scheme"
|
195
|
-
RACK_AFTER_REPLY = "rack.after_reply"
|
196
|
-
PUMA_SOCKET = "puma.socket"
|
197
|
-
PUMA_CONFIG = "puma.config"
|
198
|
-
PUMA_PEERCERT = "puma.peercert"
|
181
|
+
RACK_INPUT = "rack.input"
|
182
|
+
RACK_URL_SCHEME = "rack.url_scheme"
|
183
|
+
RACK_AFTER_REPLY = "rack.after_reply"
|
184
|
+
PUMA_SOCKET = "puma.socket"
|
185
|
+
PUMA_CONFIG = "puma.config"
|
186
|
+
PUMA_PEERCERT = "puma.peercert"
|
199
187
|
|
200
|
-
HTTP = "http"
|
201
|
-
HTTPS = "https"
|
188
|
+
HTTP = "http"
|
189
|
+
HTTPS = "https"
|
202
190
|
|
203
|
-
HTTPS_KEY = "HTTPS"
|
191
|
+
HTTPS_KEY = "HTTPS"
|
204
192
|
|
205
|
-
HTTP_VERSION = "HTTP_VERSION"
|
206
|
-
HTTP_CONNECTION = "HTTP_CONNECTION"
|
207
|
-
HTTP_EXPECT = "HTTP_EXPECT"
|
208
|
-
CONTINUE = "100-continue"
|
193
|
+
HTTP_VERSION = "HTTP_VERSION"
|
194
|
+
HTTP_CONNECTION = "HTTP_CONNECTION"
|
195
|
+
HTTP_EXPECT = "HTTP_EXPECT"
|
196
|
+
CONTINUE = "100-continue"
|
209
197
|
|
210
|
-
HTTP_11_100 = "HTTP/1.1 100 Continue\r\n\r\n"
|
211
|
-
HTTP_11_200 = "HTTP/1.1 200 OK\r\n"
|
212
|
-
HTTP_10_200 = "HTTP/1.0 200 OK\r\n"
|
198
|
+
HTTP_11_100 = "HTTP/1.1 100 Continue\r\n\r\n"
|
199
|
+
HTTP_11_200 = "HTTP/1.1 200 OK\r\n"
|
200
|
+
HTTP_10_200 = "HTTP/1.0 200 OK\r\n"
|
213
201
|
|
214
|
-
CLOSE = "close"
|
215
|
-
KEEP_ALIVE = "keep-alive"
|
202
|
+
CLOSE = "close"
|
203
|
+
KEEP_ALIVE = "keep-alive"
|
216
204
|
|
217
|
-
CONTENT_LENGTH2 = "content-length"
|
218
|
-
CONTENT_LENGTH_S = "Content-Length: "
|
219
|
-
TRANSFER_ENCODING = "transfer-encoding"
|
220
|
-
TRANSFER_ENCODING2 = "HTTP_TRANSFER_ENCODING"
|
205
|
+
CONTENT_LENGTH2 = "content-length"
|
206
|
+
CONTENT_LENGTH_S = "Content-Length: "
|
207
|
+
TRANSFER_ENCODING = "transfer-encoding"
|
208
|
+
TRANSFER_ENCODING2 = "HTTP_TRANSFER_ENCODING"
|
221
209
|
|
222
|
-
CONNECTION_CLOSE = "Connection: close\r\n"
|
223
|
-
CONNECTION_KEEP_ALIVE = "Connection: Keep-Alive\r\n"
|
210
|
+
CONNECTION_CLOSE = "Connection: close\r\n"
|
211
|
+
CONNECTION_KEEP_ALIVE = "Connection: Keep-Alive\r\n"
|
224
212
|
|
225
|
-
TRANSFER_ENCODING_CHUNKED = "Transfer-Encoding: chunked\r\n"
|
226
|
-
CLOSE_CHUNKED = "0\r\n\r\n"
|
213
|
+
TRANSFER_ENCODING_CHUNKED = "Transfer-Encoding: chunked\r\n"
|
214
|
+
CLOSE_CHUNKED = "0\r\n\r\n"
|
227
215
|
|
228
|
-
CHUNKED = "chunked"
|
216
|
+
CHUNKED = "chunked"
|
229
217
|
|
230
|
-
COLON = ": "
|
218
|
+
COLON = ": "
|
231
219
|
|
232
|
-
NEWLINE = "\n"
|
220
|
+
NEWLINE = "\n"
|
233
221
|
|
234
|
-
HIJACK_P = "rack.hijack?"
|
235
|
-
HIJACK = "rack.hijack"
|
236
|
-
HIJACK_IO = "rack.hijack_io"
|
222
|
+
HIJACK_P = "rack.hijack?"
|
223
|
+
HIJACK = "rack.hijack"
|
224
|
+
HIJACK_IO = "rack.hijack_io"
|
237
225
|
|
238
|
-
EARLY_HINTS = "rack.early_hints"
|
226
|
+
EARLY_HINTS = "rack.early_hints"
|
239
227
|
|
240
228
|
# Illegal character in the key or value of response header
|
241
|
-
DQUOTE = "\""
|
229
|
+
DQUOTE = "\""
|
242
230
|
HTTP_HEADER_DELIMITER = Regexp.escape("(),/:;<=>?@[]{}\\").freeze
|
243
231
|
ILLEGAL_HEADER_KEY_REGEX = /[\x00-\x20#{DQUOTE}#{HTTP_HEADER_DELIMITER}]/.freeze
|
244
232
|
# header values can contain HTAB?
|