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.

Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +163 -3
  3. data/README.md +21 -17
  4. data/bin/puma-wild +1 -1
  5. data/docs/compile_options.md +34 -0
  6. data/docs/fork_worker.md +1 -3
  7. data/docs/nginx.md +1 -1
  8. data/docs/testing_benchmarks_local_files.md +150 -0
  9. data/docs/testing_test_rackup_ci_files.md +36 -0
  10. data/ext/puma_http11/extconf.rb +18 -10
  11. data/ext/puma_http11/http11_parser.c +1 -1
  12. data/ext/puma_http11/http11_parser.h +1 -1
  13. data/ext/puma_http11/http11_parser.java.rl +2 -2
  14. data/ext/puma_http11/http11_parser.rl +2 -2
  15. data/ext/puma_http11/http11_parser_common.rl +2 -2
  16. data/ext/puma_http11/mini_ssl.c +63 -24
  17. data/ext/puma_http11/org/jruby/puma/Http11.java +3 -3
  18. data/ext/puma_http11/org/jruby/puma/Http11Parser.java +1 -1
  19. data/ext/puma_http11/org/jruby/puma/MiniSSL.java +166 -65
  20. data/ext/puma_http11/puma_http11.c +17 -9
  21. data/lib/puma/app/status.rb +6 -3
  22. data/lib/puma/binder.rb +37 -43
  23. data/lib/puma/cli.rb +11 -17
  24. data/lib/puma/client.rb +26 -13
  25. data/lib/puma/cluster/worker.rb +13 -11
  26. data/lib/puma/cluster/worker_handle.rb +4 -1
  27. data/lib/puma/cluster.rb +31 -30
  28. data/lib/puma/configuration.rb +74 -58
  29. data/lib/puma/const.rb +76 -88
  30. data/lib/puma/control_cli.rb +21 -18
  31. data/lib/puma/detect.rb +2 -0
  32. data/lib/puma/dsl.rb +97 -49
  33. data/lib/puma/error_logger.rb +17 -9
  34. data/lib/puma/events.rb +6 -126
  35. data/lib/puma/io_buffer.rb +39 -4
  36. data/lib/puma/jruby_restart.rb +2 -1
  37. data/lib/puma/launcher/bundle_pruner.rb +104 -0
  38. data/lib/puma/launcher.rb +107 -156
  39. data/lib/puma/log_writer.rb +137 -0
  40. data/lib/puma/minissl/context_builder.rb +23 -12
  41. data/lib/puma/minissl.rb +91 -15
  42. data/lib/puma/null_io.rb +5 -0
  43. data/lib/puma/plugin/tmp_restart.rb +1 -1
  44. data/lib/puma/rack/builder.rb +4 -4
  45. data/lib/puma/rack_default.rb +1 -1
  46. data/lib/puma/reactor.rb +4 -4
  47. data/lib/puma/request.rb +334 -162
  48. data/lib/puma/runner.rb +45 -20
  49. data/lib/puma/server.rb +55 -69
  50. data/lib/puma/single.rb +11 -11
  51. data/lib/puma/state_file.rb +2 -4
  52. data/lib/puma/systemd.rb +3 -2
  53. data/lib/puma/thread_pool.rb +16 -16
  54. data/lib/puma/util.rb +12 -14
  55. data/lib/puma.rb +12 -11
  56. data/lib/rack/handler/puma.rb +9 -9
  57. metadata +7 -3
  58. 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
- require 'puma/runner'
4
- require 'puma/util'
5
- require 'puma/plugin'
6
- require 'puma/cluster/worker_handle'
7
- require 'puma/cluster/worker'
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(cli, events)
21
- super cli, events
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
- @launcher.config.run_hooks :before_worker_fork, idx, @launcher.events
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
- @launcher.config.run_hooks :after_worker_fork, idx, @launcher.events
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
- @next_check = [
180
- @workers.reject(&:term?).map(&:ping_timeout).min,
181
- @next_check
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.stop(true) if @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.utc.iso8601,
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.utc.iso8601,
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.utc.iso8601,
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
- @launcher.events.register(:ping!) do |w|
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 @launcher.config.app_configured?
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], self
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
- @launcher.config.run_hooks :before_fork, nil, @launcher.events
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
- @launcher.events.fire(:ping!, w)
467
+ @events.fire(:ping!, w)
467
468
  if !booted && @workers.none? {|worker| worker.last_status.empty?}
468
- @launcher.events.fire_on_booted!
469
+ @events.fire_on_booted!
469
470
  booted = true
470
471
  end
471
472
  end
@@ -1,21 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'puma/rack/builder'
4
- require 'puma/plugin'
5
- require 'puma/const'
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
- include ConfigDefault
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
- # @version 5.0.0
185
- def default_max_threads
186
- Puma.mri? ? 5 : 16
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 puma_default_options
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
- :min_threads => Integer(ENV['PUMA_MIN_THREADS'] || ENV['MIN_THREADS'] || 0),
192
- :max_threads => Integer(ENV['PUMA_MAX_THREADS'] || ENV['MAX_THREADS'] || default_max_threads),
193
- :log_requests => false,
194
- :debug => false,
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/#{environment_str}.rb config/puma.rb).find do |f|
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
- require 'puma/commonlogger'
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
- def run_hooks(key, arg, events)
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.call arg
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
- events.log "WARNING hook #{key} failed with exception (#{e.class}) #{e.message}"
300
- events.debug e.backtrace.join("\n")
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
- require 'puma/dsl'
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 = "5.6.4".freeze
104
- CODE_NAME = "Birdie's Version".freeze
102
+ PUMA_VERSION = VERSION = "6.0.2"
103
+ CODE_NAME = "Sunflower"
105
104
 
106
- PUMA_SERVER_STRING = ['puma', PUMA_VERSION, CODE_NAME].join(' ').freeze
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= 'REQUEST_URI'.freeze
131
- REQUEST_PATH = 'REQUEST_PATH'.freeze
132
- QUERY_STRING = 'QUERY_STRING'.freeze
133
- CONTENT_LENGTH = "CONTENT_LENGTH".freeze
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 = 'PATH_INFO'.freeze
119
+ PATH_INFO = "PATH_INFO"
136
120
 
137
- PUMA_TMP_BASE = "puma".freeze
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".freeze,
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".freeze,
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".freeze,
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".freeze,
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".freeze,
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".freeze
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".freeze
165
- HEAD = "HEAD".freeze
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".freeze
168
- REMOTE_ADDR = "REMOTE_ADDR".freeze
169
- HTTP_X_FORWARDED_FOR = "HTTP_X_FORWARDED_FOR".freeze
170
- HTTP_X_FORWARDED_SSL = "HTTP_X_FORWARDED_SSL".freeze
171
- HTTP_X_FORWARDED_SCHEME = "HTTP_X_FORWARDED_SCHEME".freeze
172
- HTTP_X_FORWARDED_PROTO = "HTTP_X_FORWARDED_PROTO".freeze
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".freeze
175
- SERVER_PORT = "SERVER_PORT".freeze
176
- HTTP_HOST = "HTTP_HOST".freeze
177
- PORT_80 = "80".freeze
178
- PORT_443 = "443".freeze
179
- LOCALHOST = "localhost".freeze
180
- LOCALHOST_IP = "127.0.0.1".freeze
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".freeze
183
- HTTP_11 = "HTTP/1.1".freeze
170
+ SERVER_PROTOCOL = "SERVER_PROTOCOL"
171
+ HTTP_11 = "HTTP/1.1"
184
172
 
185
- SERVER_SOFTWARE = "SERVER_SOFTWARE".freeze
186
- GATEWAY_INTERFACE = "GATEWAY_INTERFACE".freeze
187
- CGI_VER = "CGI/1.2".freeze
173
+ SERVER_SOFTWARE = "SERVER_SOFTWARE"
174
+ GATEWAY_INTERFACE = "GATEWAY_INTERFACE"
175
+ CGI_VER = "CGI/1.2"
188
176
 
189
- STOP_COMMAND = "?".freeze
190
- HALT_COMMAND = "!".freeze
191
- RESTART_COMMAND = "R".freeze
177
+ STOP_COMMAND = "?"
178
+ HALT_COMMAND = "!"
179
+ RESTART_COMMAND = "R"
192
180
 
193
- RACK_INPUT = "rack.input".freeze
194
- RACK_URL_SCHEME = "rack.url_scheme".freeze
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
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".freeze
201
- HTTPS = "https".freeze
188
+ HTTP = "http"
189
+ HTTPS = "https"
202
190
 
203
- HTTPS_KEY = "HTTPS".freeze
191
+ HTTPS_KEY = "HTTPS"
204
192
 
205
- HTTP_VERSION = "HTTP_VERSION".freeze
206
- HTTP_CONNECTION = "HTTP_CONNECTION".freeze
207
- HTTP_EXPECT = "HTTP_EXPECT".freeze
208
- CONTINUE = "100-continue".freeze
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".freeze
211
- HTTP_11_200 = "HTTP/1.1 200 OK\r\n".freeze
212
- HTTP_10_200 = "HTTP/1.0 200 OK\r\n".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"
213
201
 
214
- CLOSE = "close".freeze
215
- KEEP_ALIVE = "keep-alive".freeze
202
+ CLOSE = "close"
203
+ KEEP_ALIVE = "keep-alive"
216
204
 
217
- CONTENT_LENGTH2 = "content-length".freeze
218
- CONTENT_LENGTH_S = "Content-Length: ".freeze
219
- TRANSFER_ENCODING = "transfer-encoding".freeze
220
- TRANSFER_ENCODING2 = "HTTP_TRANSFER_ENCODING".freeze
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".freeze
223
- CONNECTION_KEEP_ALIVE = "Connection: Keep-Alive\r\n".freeze
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".freeze
226
- CLOSE_CHUNKED = "0\r\n\r\n".freeze
213
+ TRANSFER_ENCODING_CHUNKED = "Transfer-Encoding: chunked\r\n"
214
+ CLOSE_CHUNKED = "0\r\n\r\n"
227
215
 
228
- CHUNKED = "chunked".freeze
216
+ CHUNKED = "chunked"
229
217
 
230
- COLON = ": ".freeze
218
+ COLON = ": "
231
219
 
232
- NEWLINE = "\n".freeze
220
+ NEWLINE = "\n"
233
221
 
234
- HIJACK_P = "rack.hijack?".freeze
235
- HIJACK = "rack.hijack".freeze
236
- HIJACK_IO = "rack.hijack_io".freeze
222
+ HIJACK_P = "rack.hijack?"
223
+ HIJACK = "rack.hijack"
224
+ HIJACK_IO = "rack.hijack_io"
237
225
 
238
- EARLY_HINTS = "rack.early_hints".freeze
226
+ EARLY_HINTS = "rack.early_hints"
239
227
 
240
228
  # Illegal character in the key or value of response header
241
- DQUOTE = "\"".freeze
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?