puma 3.11.4 → 6.0.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 +4 -4
- data/History.md +1717 -432
- data/LICENSE +23 -20
- data/README.md +190 -64
- 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 +31 -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 +2 -2
- 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/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 +61 -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 +376 -93
- 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 +250 -88
- data/ext/puma_http11/puma_http11.c +49 -57
- data/lib/puma/app/status.rb +71 -49
- data/lib/puma/binder.rb +243 -148
- data/lib/puma/cli.rb +50 -36
- data/lib/puma/client.rb +373 -233
- data/lib/puma/cluster/worker.rb +175 -0
- data/lib/puma/cluster/worker_handle.rb +97 -0
- data/lib/puma/cluster.rb +268 -235
- data/lib/puma/commonlogger.rb +4 -2
- data/lib/puma/configuration.rb +116 -88
- data/lib/puma/const.rb +49 -30
- data/lib/puma/control_cli.rb +123 -76
- data/lib/puma/detect.rb +33 -2
- data/lib/puma/dsl.rb +685 -135
- data/lib/puma/error_logger.rb +112 -0
- data/lib/puma/events.rb +17 -111
- data/lib/puma/io_buffer.rb +44 -5
- data/lib/puma/jruby_restart.rb +4 -59
- data/lib/puma/json_serialization.rb +96 -0
- data/lib/puma/launcher/bundle_pruner.rb +104 -0
- data/lib/puma/launcher.rb +196 -130
- data/lib/puma/log_writer.rb +137 -0
- data/lib/puma/minissl/context_builder.rb +92 -0
- data/lib/puma/minissl.rb +249 -69
- data/lib/puma/null_io.rb +20 -1
- data/lib/puma/plugin/tmp_restart.rb +3 -1
- data/lib/puma/plugin.rb +9 -13
- data/lib/puma/rack/builder.rb +8 -9
- data/lib/puma/rack/urlmap.rb +2 -0
- data/lib/puma/rack_default.rb +3 -1
- data/lib/puma/reactor.rb +90 -187
- data/lib/puma/request.rb +644 -0
- data/lib/puma/runner.rb +94 -71
- data/lib/puma/server.rb +337 -715
- data/lib/puma/single.rb +27 -72
- data/lib/puma/state_file.rb +46 -7
- data/lib/puma/systemd.rb +47 -0
- data/lib/puma/thread_pool.rb +184 -93
- data/lib/puma/util.rb +23 -10
- data/lib/puma.rb +60 -3
- data/lib/rack/handler/puma.rb +17 -15
- data/tools/Dockerfile +16 -0
- data/tools/trickletest.rb +0 -1
- metadata +53 -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 -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/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/1.3/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/1.3/logs.html#common
|
18
20
|
#
|
19
21
|
# lilith.local - - [07/Aug/2006 23:58:02 -0400] "GET / HTTP/1.1" 500 -
|
20
22
|
#
|
data/lib/puma/configuration.rb
CHANGED
@@ -1,24 +1,17 @@
|
|
1
|
-
|
2
|
-
require 'puma/plugin'
|
3
|
-
require 'puma/const'
|
1
|
+
# frozen_string_literal: true
|
4
2
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
DefaultTCPHost = "0.0.0.0"
|
11
|
-
DefaultTCPPort = 9292
|
12
|
-
DefaultWorkerTimeout = 60
|
13
|
-
DefaultWorkerShutdownTimeout = 30
|
14
|
-
end
|
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
|
15
7
|
|
8
|
+
module Puma
|
16
9
|
# A class used for storing "leveled" configuration options.
|
17
10
|
#
|
18
11
|
# In this class any "user" specified options take precedence over any
|
19
12
|
# "file" specified options, take precedence over any "default" options.
|
20
13
|
#
|
21
|
-
# User input is
|
14
|
+
# User input is preferred over "defaults":
|
22
15
|
# user_options = { foo: "bar" }
|
23
16
|
# default_options = { foo: "zoo" }
|
24
17
|
# options = UserFileDefaultOptions.new(user_options, default_options)
|
@@ -30,7 +23,7 @@ module Puma
|
|
30
23
|
# puts options.all_of(:foo)
|
31
24
|
# # => ["bar", "zoo"]
|
32
25
|
#
|
33
|
-
# A "file" option can be set. This config will be
|
26
|
+
# A "file" option can be set. This config will be preferred over "default" options
|
34
27
|
# but will defer to any available "user" specified options.
|
35
28
|
#
|
36
29
|
# user_options = { foo: "bar" }
|
@@ -52,9 +45,7 @@ module Puma
|
|
52
45
|
attr_reader :user_options, :file_options, :default_options
|
53
46
|
|
54
47
|
def [](key)
|
55
|
-
|
56
|
-
return file_options[key] if file_options.key?(key)
|
57
|
-
return default_options[key] if default_options.key?(key)
|
48
|
+
fetch(key)
|
58
49
|
end
|
59
50
|
|
60
51
|
def []=(key, value)
|
@@ -62,7 +53,11 @@ module Puma
|
|
62
53
|
end
|
63
54
|
|
64
55
|
def fetch(key, default_value = nil)
|
65
|
-
|
56
|
+
return user_options[key] if user_options.key?(key)
|
57
|
+
return file_options[key] if file_options.key?(key)
|
58
|
+
return default_options[key] if default_options.key?(key)
|
59
|
+
|
60
|
+
default_value
|
66
61
|
end
|
67
62
|
|
68
63
|
def all_of(key)
|
@@ -88,6 +83,12 @@ module Puma
|
|
88
83
|
end
|
89
84
|
end
|
90
85
|
end
|
86
|
+
|
87
|
+
def final_options
|
88
|
+
default_options
|
89
|
+
.merge(file_options)
|
90
|
+
.merge(user_options)
|
91
|
+
end
|
91
92
|
end
|
92
93
|
|
93
94
|
# The main configuration class of Puma.
|
@@ -104,16 +105,17 @@ module Puma
|
|
104
105
|
#
|
105
106
|
# It also handles loading plugins.
|
106
107
|
#
|
107
|
-
#
|
108
|
+
# [Note:]
|
109
|
+
# `:port` and `:host` are not valid keys. By the time they make it to the
|
108
110
|
# configuration options they are expected to be incorporated into a `:binds` key.
|
109
111
|
# Under the hood the DSL maps `port` and `host` calls to `:binds`
|
110
112
|
#
|
111
|
-
#
|
112
|
-
#
|
113
|
-
#
|
114
|
-
#
|
115
|
-
#
|
116
|
-
#
|
113
|
+
# config = Configuration.new({}) do |user_config, file_config, default_config|
|
114
|
+
# user_config.port 3003
|
115
|
+
# end
|
116
|
+
# config.load
|
117
|
+
# puts config.options[:port]
|
118
|
+
# # => 3003
|
117
119
|
#
|
118
120
|
# It is expected that `load` is called on the configuration instance after setting
|
119
121
|
# config. This method expands any values in `config_file` and puts them into the
|
@@ -124,7 +126,48 @@ module Puma
|
|
124
126
|
# is done because an environment variable may have been modified while loading
|
125
127
|
# configuration files.
|
126
128
|
class Configuration
|
127
|
-
|
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
|
+
}
|
128
171
|
|
129
172
|
def initialize(user_options={}, default_options = {}, &block)
|
130
173
|
default_options = self.puma_default_options.merge(default_options)
|
@@ -135,6 +178,10 @@ module Puma
|
|
135
178
|
@file_dsl = DSL.new(@options.file_options, self)
|
136
179
|
@default_dsl = DSL.new(@options.default_options, self)
|
137
180
|
|
181
|
+
if !@options[:prune_bundler]
|
182
|
+
default_options[:preload_app] = (@options[:workers] > 1) && Puma.forkable?
|
183
|
+
end
|
184
|
+
|
138
185
|
if block
|
139
186
|
configure(&block)
|
140
187
|
end
|
@@ -166,25 +213,21 @@ module Puma
|
|
166
213
|
end
|
167
214
|
|
168
215
|
def puma_default_options
|
216
|
+
defaults = DEFAULTS.dup
|
217
|
+
puma_options_from_env.each { |k,v| defaults[k] = v if v }
|
218
|
+
defaults
|
219
|
+
end
|
220
|
+
|
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
|
+
|
169
226
|
{
|
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
|
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'],
|
188
231
|
}
|
189
232
|
end
|
190
233
|
|
@@ -200,7 +243,7 @@ module Puma
|
|
200
243
|
return [] if files == ['-']
|
201
244
|
return files if files.any?
|
202
245
|
|
203
|
-
first_default_file = %W(config/puma/#{
|
246
|
+
first_default_file = %W(config/puma/#{@options[:environment]}.rb config/puma.rb).find do |f|
|
204
247
|
File.exist?(f)
|
205
248
|
end
|
206
249
|
|
@@ -242,16 +285,8 @@ module Puma
|
|
242
285
|
def app
|
243
286
|
found = options[:app] || load_rackup
|
244
287
|
|
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
288
|
if @options[:log_requests]
|
254
|
-
|
289
|
+
require_relative 'commonlogger'
|
255
290
|
logger = @options[:logger]
|
256
291
|
found = CommonLogger.new(found, logger)
|
257
292
|
end
|
@@ -264,16 +299,31 @@ module Puma
|
|
264
299
|
@options[:environment]
|
265
300
|
end
|
266
301
|
|
267
|
-
def environment_str
|
268
|
-
environment.respond_to?(:call) ? environment.call : environment
|
269
|
-
end
|
270
|
-
|
271
302
|
def load_plugin(name)
|
272
303
|
@plugins.create name
|
273
304
|
end
|
274
305
|
|
275
|
-
|
276
|
-
|
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)
|
310
|
+
@options.all_of(key).each do |b|
|
311
|
+
begin
|
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
|
318
|
+
rescue => e
|
319
|
+
log_writer.log "WARNING hook #{key} failed with exception (#{e.class}) #{e.message}"
|
320
|
+
log_writer.debug e.backtrace.join("\n")
|
321
|
+
end
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
def final_options
|
326
|
+
@options.final_options
|
277
327
|
end
|
278
328
|
|
279
329
|
def self.temp_path
|
@@ -285,10 +335,6 @@ module Puma
|
|
285
335
|
|
286
336
|
private
|
287
337
|
|
288
|
-
def infer_tag
|
289
|
-
File.basename(Dir.getwd)
|
290
|
-
end
|
291
|
-
|
292
338
|
# Load and use the normal Rack builder if we can, otherwise
|
293
339
|
# fallback to our minimal version.
|
294
340
|
def rack_builder
|
@@ -316,6 +362,8 @@ module Puma
|
|
316
362
|
raise "Missing rackup file '#{rackup}'" unless File.exist?(rackup)
|
317
363
|
|
318
364
|
rack_app, rack_options = rack_builder.parse_file(rackup)
|
365
|
+
rack_options = rack_options || {}
|
366
|
+
|
319
367
|
@options.file_options.merge!(rack_options)
|
320
368
|
|
321
369
|
config_ru_binds = []
|
@@ -329,31 +377,11 @@ module Puma
|
|
329
377
|
end
|
330
378
|
|
331
379
|
def self.random_token
|
332
|
-
|
333
|
-
require 'openssl'
|
334
|
-
rescue LoadError
|
335
|
-
end
|
336
|
-
|
337
|
-
count = 16
|
338
|
-
|
339
|
-
bytes = nil
|
340
|
-
|
341
|
-
if defined? OpenSSL::Random
|
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
|
380
|
+
require 'securerandom' unless defined?(SecureRandom)
|
353
381
|
|
354
|
-
|
382
|
+
SecureRandom.hex(16)
|
355
383
|
end
|
356
384
|
end
|
357
385
|
end
|
358
386
|
|
359
|
-
|
387
|
+
require_relative 'dsl'
|
data/lib/puma/const.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
#encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
2
4
|
module Puma
|
3
5
|
class UnsupportedOption < RuntimeError
|
4
6
|
end
|
@@ -74,7 +76,7 @@ module Puma
|
|
74
76
|
508 => 'Loop Detected',
|
75
77
|
510 => 'Not Extended',
|
76
78
|
511 => 'Network Authentication Required'
|
77
|
-
}
|
79
|
+
}.freeze
|
78
80
|
|
79
81
|
# For some HTTP status codes the client only expects headers.
|
80
82
|
#
|
@@ -83,7 +85,7 @@ module Puma
|
|
83
85
|
204 => true,
|
84
86
|
205 => true,
|
85
87
|
304 => true
|
86
|
-
}
|
88
|
+
}.freeze
|
87
89
|
|
88
90
|
# Frequently used constants when constructing requests or responses. Many times
|
89
91
|
# the constant just refers to a string with the same contents. Using these constants
|
@@ -98,20 +100,13 @@ module Puma
|
|
98
100
|
# too taxing on performance.
|
99
101
|
module Const
|
100
102
|
|
101
|
-
PUMA_VERSION = VERSION = "
|
102
|
-
CODE_NAME = "
|
103
|
+
PUMA_VERSION = VERSION = "6.0.1".freeze
|
104
|
+
CODE_NAME = "Sunflower".freeze
|
105
|
+
|
103
106
|
PUMA_SERVER_STRING = ['puma', PUMA_VERSION, CODE_NAME].join(' ').freeze
|
104
107
|
|
105
108
|
FAST_TRACK_KA_TIMEOUT = 0.2
|
106
109
|
|
107
|
-
# The default number of seconds for another request within a persistent
|
108
|
-
# session.
|
109
|
-
PERSISTENT_TIMEOUT = 20
|
110
|
-
|
111
|
-
# The default number of seconds to wait until we get the first data
|
112
|
-
# for the request
|
113
|
-
FIRST_DATA_TIMEOUT = 30
|
114
|
-
|
115
110
|
# How long to wait when getting some write blocking on the socket when
|
116
111
|
# sending data back
|
117
112
|
WRITE_TIMEOUT = 10
|
@@ -120,27 +115,26 @@ module Puma
|
|
120
115
|
REQUEST_URI= 'REQUEST_URI'.freeze
|
121
116
|
REQUEST_PATH = 'REQUEST_PATH'.freeze
|
122
117
|
QUERY_STRING = 'QUERY_STRING'.freeze
|
118
|
+
CONTENT_LENGTH = "CONTENT_LENGTH".freeze
|
123
119
|
|
124
120
|
PATH_INFO = 'PATH_INFO'.freeze
|
125
121
|
|
126
122
|
PUMA_TMP_BASE = "puma".freeze
|
127
123
|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
# A common header for indicating the server is too busy. Not used yet.
|
143
|
-
ERROR_503_RESPONSE = "HTTP/1.1 503 Service Unavailable\r\n\r\nBUSY".freeze
|
124
|
+
ERROR_RESPONSE = {
|
125
|
+
# Indicate that we couldn't parse the request
|
126
|
+
400 => "HTTP/1.1 400 Bad Request\r\n\r\n".freeze,
|
127
|
+
# The standard empty 404 response for bad requests. Use Error4040Handler for custom stuff.
|
128
|
+
404 => "HTTP/1.1 404 Not Found\r\nConnection: close\r\nServer: Puma #{PUMA_VERSION}\r\n\r\nNOT FOUND".freeze,
|
129
|
+
# The standard empty 408 response for requests that timed out.
|
130
|
+
408 => "HTTP/1.1 408 Request Timeout\r\nConnection: close\r\nServer: Puma #{PUMA_VERSION}\r\n\r\n".freeze,
|
131
|
+
# Indicate that there was an internal error, obviously.
|
132
|
+
500 => "HTTP/1.1 500 Internal Server Error\r\n\r\n".freeze,
|
133
|
+
# Incorrect or invalid header value
|
134
|
+
501 => "HTTP/1.1 501 Not Implemented\r\n\r\n".freeze,
|
135
|
+
# A common header for indicating the server is too busy. Not used yet.
|
136
|
+
503 => "HTTP/1.1 503 Service Unavailable\r\n\r\nBUSY".freeze
|
137
|
+
}.freeze
|
144
138
|
|
145
139
|
# The basic max request size we'll try to read.
|
146
140
|
CHUNK_SIZE = 16 * 1024
|
@@ -154,10 +148,21 @@ module Puma
|
|
154
148
|
|
155
149
|
REQUEST_METHOD = "REQUEST_METHOD".freeze
|
156
150
|
HEAD = "HEAD".freeze
|
151
|
+
GET = "GET".freeze
|
152
|
+
POST = "POST".freeze
|
153
|
+
PUT = "PUT".freeze
|
154
|
+
DELETE = "DELETE".freeze
|
155
|
+
OPTIONS = "OPTIONS".freeze
|
156
|
+
TRACE = "TRACE".freeze
|
157
|
+
PATCH = "PATCH".freeze
|
158
|
+
SUPPORTED_HTTP_METHODS = [HEAD, GET, POST, PUT, DELETE, OPTIONS, TRACE, PATCH].freeze
|
157
159
|
# ETag is based on the apache standard of hex mtime-size-inode (inode is 0 on win32)
|
158
160
|
LINE_END = "\r\n".freeze
|
159
161
|
REMOTE_ADDR = "REMOTE_ADDR".freeze
|
160
162
|
HTTP_X_FORWARDED_FOR = "HTTP_X_FORWARDED_FOR".freeze
|
163
|
+
HTTP_X_FORWARDED_SSL = "HTTP_X_FORWARDED_SSL".freeze
|
164
|
+
HTTP_X_FORWARDED_SCHEME = "HTTP_X_FORWARDED_SCHEME".freeze
|
165
|
+
HTTP_X_FORWARDED_PROTO = "HTTP_X_FORWARDED_PROTO".freeze
|
161
166
|
|
162
167
|
SERVER_NAME = "SERVER_NAME".freeze
|
163
168
|
SERVER_PORT = "SERVER_PORT".freeze
|
@@ -165,8 +170,10 @@ module Puma
|
|
165
170
|
PORT_80 = "80".freeze
|
166
171
|
PORT_443 = "443".freeze
|
167
172
|
LOCALHOST = "localhost".freeze
|
168
|
-
|
169
|
-
|
173
|
+
LOCALHOST_IPV4 = "127.0.0.1".freeze
|
174
|
+
LOCALHOST_IPV6 = "::1".freeze
|
175
|
+
UNSPECIFIED_IPV4 = "0.0.0.0".freeze
|
176
|
+
UNSPECIFIED_IPV6 = "::".freeze
|
170
177
|
|
171
178
|
SERVER_PROTOCOL = "SERVER_PROTOCOL".freeze
|
172
179
|
HTTP_11 = "HTTP/1.1".freeze
|
@@ -225,5 +232,17 @@ module Puma
|
|
225
232
|
HIJACK_IO = "rack.hijack_io".freeze
|
226
233
|
|
227
234
|
EARLY_HINTS = "rack.early_hints".freeze
|
235
|
+
|
236
|
+
# Illegal character in the key or value of response header
|
237
|
+
DQUOTE = "\"".freeze
|
238
|
+
HTTP_HEADER_DELIMITER = Regexp.escape("(),/:;<=>?@[]{}\\").freeze
|
239
|
+
ILLEGAL_HEADER_KEY_REGEX = /[\x00-\x20#{DQUOTE}#{HTTP_HEADER_DELIMITER}]/.freeze
|
240
|
+
# header values can contain HTAB?
|
241
|
+
ILLEGAL_HEADER_VALUE_REGEX = /[\x00-\x08\x0A-\x1F]/.freeze
|
242
|
+
|
243
|
+
# Banned keys of response header
|
244
|
+
BANNED_HEADER_KEY = /\A(rack\.|status\z)/.freeze
|
245
|
+
|
246
|
+
PROXY_PROTOCOL_V1_REGEX = /^PROXY (?:TCP4|TCP6|UNKNOWN) ([^\r]+)\r\n/.freeze
|
228
247
|
end
|
229
248
|
end
|