puma 4.3.12 → 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 +1618 -521
- data/LICENSE +23 -20
- data/README.md +130 -42
- data/bin/puma-wild +3 -9
- data/docs/architecture.md +63 -26
- data/docs/compile_options.md +55 -0
- data/docs/deployment.md +60 -69
- data/docs/fork_worker.md +31 -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 +15 -15
- data/docs/rails_dev_mode.md +28 -0
- data/docs/restart.md +46 -23
- data/docs/signals.md +13 -11
- data/docs/stats.md +142 -0
- data/docs/systemd.md +85 -128
- 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 -4
- data/ext/puma_http11/ext_help.h +1 -1
- data/ext/puma_http11/extconf.rb +49 -12
- data/ext/puma_http11/http11_parser.c +46 -48
- data/ext/puma_http11/http11_parser.h +2 -2
- data/ext/puma_http11/http11_parser.java.rl +3 -3
- data/ext/puma_http11/http11_parser.rl +3 -3
- data/ext/puma_http11/http11_parser_common.rl +2 -2
- data/ext/puma_http11/mini_ssl.c +250 -93
- data/ext/puma_http11/no_ssl/PumaHttp11Service.java +15 -0
- data/ext/puma_http11/org/jruby/puma/Http11.java +6 -6
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +4 -6
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +241 -96
- data/ext/puma_http11/puma_http11.c +46 -57
- data/lib/puma/app/status.rb +52 -38
- data/lib/puma/binder.rb +232 -119
- data/lib/puma/cli.rb +33 -33
- data/lib/puma/client.rb +129 -88
- data/lib/puma/cluster/worker.rb +175 -0
- data/lib/puma/cluster/worker_handle.rb +97 -0
- data/lib/puma/cluster.rb +224 -231
- data/lib/puma/commonlogger.rb +2 -2
- data/lib/puma/configuration.rb +112 -87
- data/lib/puma/const.rb +86 -91
- data/lib/puma/control_cli.rb +99 -79
- data/lib/puma/detect.rb +31 -2
- data/lib/puma/dsl.rb +426 -110
- data/lib/puma/error_logger.rb +112 -0
- data/lib/puma/events.rb +16 -115
- data/lib/puma/io_buffer.rb +44 -2
- data/lib/puma/jruby_restart.rb +2 -59
- data/lib/puma/json_serialization.rb +96 -0
- data/lib/puma/launcher/bundle_pruner.rb +104 -0
- data/lib/puma/launcher.rb +170 -148
- data/lib/puma/log_writer.rb +137 -0
- data/lib/puma/minissl/context_builder.rb +35 -19
- data/lib/puma/minissl.rb +213 -55
- data/lib/puma/null_io.rb +18 -1
- data/lib/puma/plugin/tmp_restart.rb +1 -1
- data/lib/puma/plugin.rb +3 -12
- data/lib/puma/rack/builder.rb +5 -9
- data/lib/puma/rack_default.rb +1 -1
- data/lib/puma/reactor.rb +85 -369
- data/lib/puma/request.rb +644 -0
- data/lib/puma/runner.rb +86 -76
- data/lib/puma/server.rb +306 -793
- data/lib/puma/single.rb +18 -74
- data/lib/puma/state_file.rb +45 -8
- data/lib/puma/systemd.rb +47 -0
- data/lib/puma/thread_pool.rb +136 -68
- data/lib/puma/util.rb +21 -4
- data/lib/puma.rb +54 -7
- data/lib/rack/handler/puma.rb +11 -12
- data/tools/{docker/Dockerfile → Dockerfile} +1 -1
- metadata +31 -23
- data/docs/tcp_mode.md +0 -96
- data/ext/puma_http11/io_buffer.c +0 -155
- data/ext/puma_http11/org/jruby/puma/IOBuffer.java +0 -72
- data/lib/puma/accept_nonblock.rb +0 -29
- 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
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
@@ -1,20 +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
|
-
DefaultWorkerTimeout = 60
|
15
|
-
DefaultWorkerShutdownTimeout = 30
|
16
|
-
end
|
17
|
-
|
18
9
|
# A class used for storing "leveled" configuration options.
|
19
10
|
#
|
20
11
|
# In this class any "user" specified options take precedence over any
|
@@ -54,9 +45,7 @@ module Puma
|
|
54
45
|
attr_reader :user_options, :file_options, :default_options
|
55
46
|
|
56
47
|
def [](key)
|
57
|
-
|
58
|
-
return file_options[key] if file_options.key?(key)
|
59
|
-
return default_options[key] if default_options.key?(key)
|
48
|
+
fetch(key)
|
60
49
|
end
|
61
50
|
|
62
51
|
def []=(key, value)
|
@@ -64,7 +53,11 @@ module Puma
|
|
64
53
|
end
|
65
54
|
|
66
55
|
def fetch(key, default_value = nil)
|
67
|
-
|
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
|
68
61
|
end
|
69
62
|
|
70
63
|
def all_of(key)
|
@@ -90,6 +83,12 @@ module Puma
|
|
90
83
|
end
|
91
84
|
end
|
92
85
|
end
|
86
|
+
|
87
|
+
def final_options
|
88
|
+
default_options
|
89
|
+
.merge(file_options)
|
90
|
+
.merge(user_options)
|
91
|
+
end
|
93
92
|
end
|
94
93
|
|
95
94
|
# The main configuration class of Puma.
|
@@ -106,16 +105,17 @@ module Puma
|
|
106
105
|
#
|
107
106
|
# It also handles loading plugins.
|
108
107
|
#
|
109
|
-
#
|
108
|
+
# [Note:]
|
109
|
+
# `:port` and `:host` are not valid keys. By the time they make it to the
|
110
110
|
# configuration options they are expected to be incorporated into a `:binds` key.
|
111
111
|
# Under the hood the DSL maps `port` and `host` calls to `:binds`
|
112
112
|
#
|
113
|
-
#
|
114
|
-
#
|
115
|
-
#
|
116
|
-
#
|
117
|
-
#
|
118
|
-
#
|
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
|
119
119
|
#
|
120
120
|
# It is expected that `load` is called on the configuration instance after setting
|
121
121
|
# config. This method expands any values in `config_file` and puts them into the
|
@@ -126,7 +126,48 @@ module Puma
|
|
126
126
|
# is done because an environment variable may have been modified while loading
|
127
127
|
# configuration files.
|
128
128
|
class Configuration
|
129
|
-
|
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
|
+
}
|
130
171
|
|
131
172
|
def initialize(user_options={}, default_options = {}, &block)
|
132
173
|
default_options = self.puma_default_options.merge(default_options)
|
@@ -137,6 +178,10 @@ module Puma
|
|
137
178
|
@file_dsl = DSL.new(@options.file_options, self)
|
138
179
|
@default_dsl = DSL.new(@options.default_options, self)
|
139
180
|
|
181
|
+
if !@options[:prune_bundler]
|
182
|
+
default_options[:preload_app] = (@options[:workers] > 1) && Puma.forkable?
|
183
|
+
end
|
184
|
+
|
140
185
|
if block
|
141
186
|
configure(&block)
|
142
187
|
end
|
@@ -168,26 +213,21 @@ module Puma
|
|
168
213
|
end
|
169
214
|
|
170
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
|
+
|
171
226
|
{
|
172
|
-
:
|
173
|
-
:
|
174
|
-
:
|
175
|
-
:
|
176
|
-
:binds => ["tcp://#{DefaultTCPHost}:#{DefaultTCPPort}"],
|
177
|
-
:workers => 0,
|
178
|
-
:daemon => false,
|
179
|
-
:mode => :http,
|
180
|
-
:worker_timeout => DefaultWorkerTimeout,
|
181
|
-
:worker_boot_timeout => DefaultWorkerTimeout,
|
182
|
-
:worker_shutdown_timeout => DefaultWorkerShutdownTimeout,
|
183
|
-
:remote_address => :socket,
|
184
|
-
:tag => method(:infer_tag),
|
185
|
-
:environment => -> { ENV['RACK_ENV'] || "development" },
|
186
|
-
:rackup => DefaultRackup,
|
187
|
-
:logger => STDOUT,
|
188
|
-
:persistent_timeout => Const::PERSISTENT_TIMEOUT,
|
189
|
-
:first_data_timeout => Const::FIRST_DATA_TIMEOUT,
|
190
|
-
:raise_exception_on_sigterm => 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'],
|
191
231
|
}
|
192
232
|
end
|
193
233
|
|
@@ -203,7 +243,7 @@ module Puma
|
|
203
243
|
return [] if files == ['-']
|
204
244
|
return files if files.any?
|
205
245
|
|
206
|
-
first_default_file = %W(config/puma/#{
|
246
|
+
first_default_file = %W(config/puma/#{@options[:environment]}.rb config/puma.rb).find do |f|
|
207
247
|
File.exist?(f)
|
208
248
|
end
|
209
249
|
|
@@ -245,16 +285,8 @@ module Puma
|
|
245
285
|
def app
|
246
286
|
found = options[:app] || load_rackup
|
247
287
|
|
248
|
-
if @options[:mode] == :tcp
|
249
|
-
require 'puma/tcp_logger'
|
250
|
-
|
251
|
-
logger = @options[:logger]
|
252
|
-
quiet = !@options[:log_requests]
|
253
|
-
return TCPLogger.new(logger, found, quiet)
|
254
|
-
end
|
255
|
-
|
256
288
|
if @options[:log_requests]
|
257
|
-
|
289
|
+
require_relative 'commonlogger'
|
258
290
|
logger = @options[:logger]
|
259
291
|
found = CommonLogger.new(found, logger)
|
260
292
|
end
|
@@ -267,16 +299,31 @@ module Puma
|
|
267
299
|
@options[:environment]
|
268
300
|
end
|
269
301
|
|
270
|
-
def environment_str
|
271
|
-
environment.respond_to?(:call) ? environment.call : environment
|
272
|
-
end
|
273
|
-
|
274
302
|
def load_plugin(name)
|
275
303
|
@plugins.create name
|
276
304
|
end
|
277
305
|
|
278
|
-
|
279
|
-
|
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
|
280
327
|
end
|
281
328
|
|
282
329
|
def self.temp_path
|
@@ -288,10 +335,6 @@ module Puma
|
|
288
335
|
|
289
336
|
private
|
290
337
|
|
291
|
-
def infer_tag
|
292
|
-
File.basename(Dir.getwd)
|
293
|
-
end
|
294
|
-
|
295
338
|
# Load and use the normal Rack builder if we can, otherwise
|
296
339
|
# fallback to our minimal version.
|
297
340
|
def rack_builder
|
@@ -319,6 +362,8 @@ module Puma
|
|
319
362
|
raise "Missing rackup file '#{rackup}'" unless File.exist?(rackup)
|
320
363
|
|
321
364
|
rack_app, rack_options = rack_builder.parse_file(rackup)
|
365
|
+
rack_options = rack_options || {}
|
366
|
+
|
322
367
|
@options.file_options.merge!(rack_options)
|
323
368
|
|
324
369
|
config_ru_binds = []
|
@@ -332,31 +377,11 @@ module Puma
|
|
332
377
|
end
|
333
378
|
|
334
379
|
def self.random_token
|
335
|
-
|
336
|
-
require 'openssl'
|
337
|
-
rescue LoadError
|
338
|
-
end
|
339
|
-
|
340
|
-
count = 16
|
341
|
-
|
342
|
-
bytes = nil
|
343
|
-
|
344
|
-
if defined? OpenSSL::Random
|
345
|
-
bytes = OpenSSL::Random.random_bytes(count)
|
346
|
-
elsif File.exist?("/dev/urandom")
|
347
|
-
File.open('/dev/urandom') { |f| bytes = f.read(count) }
|
348
|
-
end
|
349
|
-
|
350
|
-
if bytes
|
351
|
-
token = "".dup
|
352
|
-
bytes.each_byte { |b| token << b.to_s(16) }
|
353
|
-
else
|
354
|
-
token = (0..count).to_a.map { rand(255).to_s(16) }.join
|
355
|
-
end
|
380
|
+
require 'securerandom' unless defined?(SecureRandom)
|
356
381
|
|
357
|
-
|
382
|
+
SecureRandom.hex(16)
|
358
383
|
end
|
359
384
|
end
|
360
385
|
end
|
361
386
|
|
362
|
-
|
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,54 +99,40 @@ module Puma
|
|
100
99
|
# too taxing on performance.
|
101
100
|
module Const
|
102
101
|
|
103
|
-
PUMA_VERSION = VERSION = "
|
104
|
-
CODE_NAME = "
|
105
|
-
PUMA_SERVER_STRING = ['puma', PUMA_VERSION, CODE_NAME].join(' ').freeze
|
106
|
-
|
107
|
-
FAST_TRACK_KA_TIMEOUT = 0.2
|
102
|
+
PUMA_VERSION = VERSION = "6.0.2"
|
103
|
+
CODE_NAME = "Sunflower"
|
108
104
|
|
109
|
-
|
110
|
-
# session.
|
111
|
-
PERSISTENT_TIMEOUT = 20
|
105
|
+
PUMA_SERVER_STRING = ["puma", PUMA_VERSION, CODE_NAME].join(" ").freeze
|
112
106
|
|
113
|
-
|
114
|
-
# for the request
|
115
|
-
FIRST_DATA_TIMEOUT = 30
|
107
|
+
FAST_TRACK_KA_TIMEOUT = 0.2
|
116
108
|
|
117
109
|
# How long to wait when getting some write blocking on the socket when
|
118
110
|
# sending data back
|
119
111
|
WRITE_TIMEOUT = 10
|
120
112
|
|
121
|
-
# How many requests to attempt inline before sending a client back to
|
122
|
-
# the reactor to be subject to normal ordering. The idea here is that
|
123
|
-
# we amortize the cost of going back to the reactor for a well behaved
|
124
|
-
# but very "greedy" client across 10 requests. This prevents a not
|
125
|
-
# well behaved client from monopolizing the thread forever.
|
126
|
-
MAX_FAST_INLINE = 10
|
127
|
-
|
128
113
|
# The original URI requested by the client.
|
129
|
-
REQUEST_URI=
|
130
|
-
REQUEST_PATH =
|
131
|
-
QUERY_STRING =
|
132
|
-
CONTENT_LENGTH = "CONTENT_LENGTH"
|
114
|
+
REQUEST_URI= "REQUEST_URI"
|
115
|
+
REQUEST_PATH = "REQUEST_PATH"
|
116
|
+
QUERY_STRING = "QUERY_STRING"
|
117
|
+
CONTENT_LENGTH = "CONTENT_LENGTH"
|
133
118
|
|
134
|
-
PATH_INFO =
|
119
|
+
PATH_INFO = "PATH_INFO"
|
135
120
|
|
136
|
-
PUMA_TMP_BASE = "puma"
|
121
|
+
PUMA_TMP_BASE = "puma"
|
137
122
|
|
138
123
|
ERROR_RESPONSE = {
|
139
124
|
# Indicate that we couldn't parse the request
|
140
|
-
400 => "HTTP/1.1 400 Bad Request\r\n\r\n"
|
125
|
+
400 => "HTTP/1.1 400 Bad Request\r\n\r\n",
|
141
126
|
# The standard empty 404 response for bad requests. Use Error4040Handler for custom stuff.
|
142
|
-
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",
|
143
128
|
# The standard empty 408 response for requests that timed out.
|
144
|
-
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",
|
145
130
|
# Indicate that there was an internal error, obviously.
|
146
|
-
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",
|
147
132
|
# Incorrect or invalid header value
|
148
|
-
501 => "HTTP/1.1 501 Not Implemented\r\n\r\n"
|
133
|
+
501 => "HTTP/1.1 501 Not Implemented\r\n\r\n",
|
149
134
|
# A common header for indicating the server is too busy. Not used yet.
|
150
|
-
503 => "HTTP/1.1 503 Service Unavailable\r\n\r\nBUSY"
|
135
|
+
503 => "HTTP/1.1 503 Service Unavailable\r\n\r\nBUSY"
|
151
136
|
}.freeze
|
152
137
|
|
153
138
|
# The basic max request size we'll try to read.
|
@@ -160,86 +145,96 @@ module Puma
|
|
160
145
|
# Maximum request body size before it is moved out of memory and into a tempfile for reading.
|
161
146
|
MAX_BODY = MAX_HEADER
|
162
147
|
|
163
|
-
REQUEST_METHOD = "REQUEST_METHOD"
|
164
|
-
HEAD = "HEAD"
|
148
|
+
REQUEST_METHOD = "REQUEST_METHOD"
|
149
|
+
HEAD = "HEAD"
|
150
|
+
SUPPORTED_HTTP_METHODS = %w[HEAD GET POST PUT DELETE OPTIONS TRACE PATCH].freeze
|
165
151
|
# ETag is based on the apache standard of hex mtime-size-inode (inode is 0 on win32)
|
166
|
-
LINE_END = "\r\n"
|
167
|
-
REMOTE_ADDR = "REMOTE_ADDR"
|
168
|
-
HTTP_X_FORWARDED_FOR = "HTTP_X_FORWARDED_FOR"
|
169
|
-
HTTP_X_FORWARDED_SSL = "HTTP_X_FORWARDED_SSL"
|
170
|
-
HTTP_X_FORWARDED_SCHEME = "HTTP_X_FORWARDED_SCHEME"
|
171
|
-
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"
|
158
|
+
|
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 = "::"
|
172
169
|
|
173
|
-
|
174
|
-
|
175
|
-
HTTP_HOST = "HTTP_HOST".freeze
|
176
|
-
PORT_80 = "80".freeze
|
177
|
-
PORT_443 = "443".freeze
|
178
|
-
LOCALHOST = "localhost".freeze
|
179
|
-
LOCALHOST_IP = "127.0.0.1".freeze
|
180
|
-
LOCALHOST_ADDR = "127.0.0.1:0".freeze
|
170
|
+
SERVER_PROTOCOL = "SERVER_PROTOCOL"
|
171
|
+
HTTP_11 = "HTTP/1.1"
|
181
172
|
|
182
|
-
|
183
|
-
|
173
|
+
SERVER_SOFTWARE = "SERVER_SOFTWARE"
|
174
|
+
GATEWAY_INTERFACE = "GATEWAY_INTERFACE"
|
175
|
+
CGI_VER = "CGI/1.2"
|
184
176
|
|
185
|
-
|
186
|
-
|
187
|
-
|
177
|
+
STOP_COMMAND = "?"
|
178
|
+
HALT_COMMAND = "!"
|
179
|
+
RESTART_COMMAND = "R"
|
188
180
|
|
189
|
-
|
190
|
-
|
191
|
-
|
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"
|
192
187
|
|
193
|
-
|
194
|
-
|
195
|
-
RACK_AFTER_REPLY = "rack.after_reply".freeze
|
196
|
-
PUMA_SOCKET = "puma.socket".freeze
|
197
|
-
PUMA_CONFIG = "puma.config".freeze
|
198
|
-
PUMA_PEERCERT = "puma.peercert".freeze
|
188
|
+
HTTP = "http"
|
189
|
+
HTTPS = "https"
|
199
190
|
|
200
|
-
|
201
|
-
HTTPS = "https".freeze
|
191
|
+
HTTPS_KEY = "HTTPS"
|
202
192
|
|
203
|
-
|
193
|
+
HTTP_VERSION = "HTTP_VERSION"
|
194
|
+
HTTP_CONNECTION = "HTTP_CONNECTION"
|
195
|
+
HTTP_EXPECT = "HTTP_EXPECT"
|
196
|
+
CONTINUE = "100-continue"
|
204
197
|
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
CONTINUE = "100-continue".freeze
|
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"
|
209
201
|
|
210
|
-
|
211
|
-
|
212
|
-
HTTP_10_200 = "HTTP/1.0 200 OK\r\n".freeze
|
202
|
+
CLOSE = "close"
|
203
|
+
KEEP_ALIVE = "keep-alive"
|
213
204
|
|
214
|
-
|
215
|
-
|
205
|
+
CONTENT_LENGTH2 = "content-length"
|
206
|
+
CONTENT_LENGTH_S = "Content-Length: "
|
207
|
+
TRANSFER_ENCODING = "transfer-encoding"
|
208
|
+
TRANSFER_ENCODING2 = "HTTP_TRANSFER_ENCODING"
|
216
209
|
|
217
|
-
|
218
|
-
|
219
|
-
TRANSFER_ENCODING = "transfer-encoding".freeze
|
220
|
-
TRANSFER_ENCODING2 = "HTTP_TRANSFER_ENCODING".freeze
|
210
|
+
CONNECTION_CLOSE = "Connection: close\r\n"
|
211
|
+
CONNECTION_KEEP_ALIVE = "Connection: Keep-Alive\r\n"
|
221
212
|
|
222
|
-
|
223
|
-
|
213
|
+
TRANSFER_ENCODING_CHUNKED = "Transfer-Encoding: chunked\r\n"
|
214
|
+
CLOSE_CHUNKED = "0\r\n\r\n"
|
224
215
|
|
225
|
-
|
226
|
-
CLOSE_CHUNKED = "0\r\n\r\n".freeze
|
216
|
+
CHUNKED = "chunked"
|
227
217
|
|
228
|
-
|
218
|
+
COLON = ": "
|
229
219
|
|
230
|
-
|
220
|
+
NEWLINE = "\n"
|
231
221
|
|
232
|
-
|
233
|
-
|
222
|
+
HIJACK_P = "rack.hijack?"
|
223
|
+
HIJACK = "rack.hijack"
|
224
|
+
HIJACK_IO = "rack.hijack_io"
|
234
225
|
|
235
|
-
|
236
|
-
HIJACK = "rack.hijack".freeze
|
237
|
-
HIJACK_IO = "rack.hijack_io".freeze
|
226
|
+
EARLY_HINTS = "rack.early_hints"
|
238
227
|
|
239
|
-
|
228
|
+
# Illegal character in the key or value of response header
|
229
|
+
DQUOTE = "\""
|
230
|
+
HTTP_HEADER_DELIMITER = Regexp.escape("(),/:;<=>?@[]{}\\").freeze
|
231
|
+
ILLEGAL_HEADER_KEY_REGEX = /[\x00-\x20#{DQUOTE}#{HTTP_HEADER_DELIMITER}]/.freeze
|
232
|
+
# header values can contain HTAB?
|
233
|
+
ILLEGAL_HEADER_VALUE_REGEX = /[\x00-\x08\x0A-\x1F]/.freeze
|
240
234
|
|
241
|
-
#
|
242
|
-
|
235
|
+
# Banned keys of response header
|
236
|
+
BANNED_HEADER_KEY = /\A(rack\.|status\z)/.freeze
|
243
237
|
|
238
|
+
PROXY_PROTOCOL_V1_REGEX = /^PROXY (?:TCP4|TCP6|UNKNOWN) ([^\r]+)\r\n/.freeze
|
244
239
|
end
|
245
240
|
end
|