ed-precompiled_puma 7.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. checksums.yaml +7 -0
  2. data/History.md +3172 -0
  3. data/LICENSE +29 -0
  4. data/README.md +477 -0
  5. data/bin/puma +10 -0
  6. data/bin/puma-wild +25 -0
  7. data/bin/pumactl +12 -0
  8. data/docs/architecture.md +74 -0
  9. data/docs/compile_options.md +55 -0
  10. data/docs/deployment.md +102 -0
  11. data/docs/fork_worker.md +41 -0
  12. data/docs/images/puma-connection-flow-no-reactor.png +0 -0
  13. data/docs/images/puma-connection-flow.png +0 -0
  14. data/docs/images/puma-general-arch.png +0 -0
  15. data/docs/java_options.md +54 -0
  16. data/docs/jungle/README.md +9 -0
  17. data/docs/jungle/rc.d/README.md +74 -0
  18. data/docs/jungle/rc.d/puma +61 -0
  19. data/docs/jungle/rc.d/puma.conf +10 -0
  20. data/docs/kubernetes.md +80 -0
  21. data/docs/nginx.md +80 -0
  22. data/docs/plugins.md +42 -0
  23. data/docs/rails_dev_mode.md +28 -0
  24. data/docs/restart.md +65 -0
  25. data/docs/signals.md +98 -0
  26. data/docs/stats.md +148 -0
  27. data/docs/systemd.md +253 -0
  28. data/docs/testing_benchmarks_local_files.md +150 -0
  29. data/docs/testing_test_rackup_ci_files.md +36 -0
  30. data/ext/puma_http11/PumaHttp11Service.java +17 -0
  31. data/ext/puma_http11/ext_help.h +15 -0
  32. data/ext/puma_http11/extconf.rb +65 -0
  33. data/ext/puma_http11/http11_parser.c +1057 -0
  34. data/ext/puma_http11/http11_parser.h +65 -0
  35. data/ext/puma_http11/http11_parser.java.rl +145 -0
  36. data/ext/puma_http11/http11_parser.rl +149 -0
  37. data/ext/puma_http11/http11_parser_common.rl +54 -0
  38. data/ext/puma_http11/mini_ssl.c +852 -0
  39. data/ext/puma_http11/no_ssl/PumaHttp11Service.java +15 -0
  40. data/ext/puma_http11/org/jruby/puma/Http11.java +257 -0
  41. data/ext/puma_http11/org/jruby/puma/Http11Parser.java +455 -0
  42. data/ext/puma_http11/org/jruby/puma/MiniSSL.java +509 -0
  43. data/ext/puma_http11/puma_http11.c +507 -0
  44. data/lib/puma/app/status.rb +96 -0
  45. data/lib/puma/binder.rb +511 -0
  46. data/lib/puma/cli.rb +245 -0
  47. data/lib/puma/client.rb +720 -0
  48. data/lib/puma/cluster/worker.rb +182 -0
  49. data/lib/puma/cluster/worker_handle.rb +127 -0
  50. data/lib/puma/cluster.rb +635 -0
  51. data/lib/puma/cluster_accept_loop_delay.rb +91 -0
  52. data/lib/puma/commonlogger.rb +115 -0
  53. data/lib/puma/configuration.rb +452 -0
  54. data/lib/puma/const.rb +307 -0
  55. data/lib/puma/control_cli.rb +320 -0
  56. data/lib/puma/detect.rb +47 -0
  57. data/lib/puma/dsl.rb +1480 -0
  58. data/lib/puma/error_logger.rb +115 -0
  59. data/lib/puma/events.rb +72 -0
  60. data/lib/puma/io_buffer.rb +50 -0
  61. data/lib/puma/jruby_restart.rb +11 -0
  62. data/lib/puma/json_serialization.rb +96 -0
  63. data/lib/puma/launcher/bundle_pruner.rb +104 -0
  64. data/lib/puma/launcher.rb +496 -0
  65. data/lib/puma/log_writer.rb +147 -0
  66. data/lib/puma/minissl/context_builder.rb +96 -0
  67. data/lib/puma/minissl.rb +463 -0
  68. data/lib/puma/null_io.rb +101 -0
  69. data/lib/puma/plugin/systemd.rb +90 -0
  70. data/lib/puma/plugin/tmp_restart.rb +36 -0
  71. data/lib/puma/plugin.rb +111 -0
  72. data/lib/puma/rack/builder.rb +297 -0
  73. data/lib/puma/rack/urlmap.rb +93 -0
  74. data/lib/puma/rack_default.rb +24 -0
  75. data/lib/puma/reactor.rb +140 -0
  76. data/lib/puma/request.rb +701 -0
  77. data/lib/puma/runner.rb +211 -0
  78. data/lib/puma/sd_notify.rb +146 -0
  79. data/lib/puma/server.rb +734 -0
  80. data/lib/puma/single.rb +72 -0
  81. data/lib/puma/state_file.rb +69 -0
  82. data/lib/puma/thread_pool.rb +402 -0
  83. data/lib/puma/util.rb +134 -0
  84. data/lib/puma.rb +93 -0
  85. data/lib/rack/handler/puma.rb +144 -0
  86. data/tools/Dockerfile +18 -0
  87. data/tools/trickletest.rb +44 -0
  88. metadata +152 -0
@@ -0,0 +1,496 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'log_writer'
4
+ require_relative 'events'
5
+ require_relative 'detect'
6
+ require_relative 'cluster'
7
+ require_relative 'single'
8
+ require_relative 'const'
9
+ require_relative 'binder'
10
+
11
+ module Puma
12
+ # Puma::Launcher is the single entry point for starting a Puma server based on user
13
+ # configuration. It is responsible for taking user supplied arguments and resolving them
14
+ # with configuration in `config/puma.rb` or `config/puma/<env>.rb`.
15
+ #
16
+ # It is responsible for either launching a cluster of Puma workers or a single
17
+ # puma server.
18
+ class Launcher
19
+ autoload :BundlePruner, 'puma/launcher/bundle_pruner'
20
+
21
+ # Returns an instance of Launcher
22
+ #
23
+ # +conf+ A Puma::Configuration object indicating how to run the server.
24
+ #
25
+ # +launcher_args+ A Hash that has a few optional keys.
26
+ # - +:log_writer+:: Expected to hold an object similar to `Puma::LogWriter.stdio`.
27
+ # This object will be responsible for broadcasting Puma's internal state
28
+ # to a logging destination.
29
+ # - +:events+:: Expected to hold an object similar to `Puma::Events`.
30
+ # - +:argv+:: Expected to be an array of strings.
31
+ # - +:env+:: Expected to hold a hash of environment variables.
32
+ #
33
+ # These arguments are re-used when restarting the puma server.
34
+ #
35
+ # Examples:
36
+ #
37
+ # conf = Puma::Configuration.new do |user_config|
38
+ # user_config.threads 1, 10
39
+ # user_config.app do |env|
40
+ # [200, {}, ["hello world"]]
41
+ # end
42
+ # end
43
+ # Puma::Launcher.new(conf, log_writer: Puma::LogWriter.stdio).run
44
+ def initialize(conf, launcher_args={})
45
+ @runner = nil
46
+ @log_writer = launcher_args[:log_writer] || LogWriter::DEFAULT
47
+ @events = launcher_args[:events] || Events.new
48
+ @argv = launcher_args[:argv] || []
49
+ @original_argv = @argv.dup
50
+ @config = conf
51
+
52
+ env = launcher_args.delete(:env) || ENV
53
+
54
+ @config.clamp
55
+ @options = @config.options
56
+
57
+ @options[:log_writer] = @log_writer
58
+ @options[:logger] = @log_writer if clustered?
59
+
60
+ # Advertise the Configuration
61
+ Puma.cli_config = @config if defined?(Puma.cli_config)
62
+ log_config if env['PUMA_LOG_CONFIG']
63
+
64
+ @binder = Binder.new(@log_writer, @options)
65
+ @binder.create_inherited_fds(env).each { |k| env.delete k }
66
+ @binder.create_activated_fds(env).each { |k| env.delete k }
67
+
68
+ @environment = @config.environment
69
+
70
+ # Load the systemd integration if we detect systemd's NOTIFY_SOCKET.
71
+ # Skip this on JRuby though, because it is incompatible with the systemd
72
+ # integration due to https://github.com/jruby/jruby/issues/6504
73
+ if ENV["NOTIFY_SOCKET"] && !Puma.jruby? && !ENV["PUMA_SKIP_SYSTEMD"]
74
+ @config.plugins.create('systemd')
75
+ end
76
+
77
+ if @options[:bind_to_activated_sockets]
78
+ @options[:binds] = @binder.synthesize_binds_from_activated_fs(
79
+ @options[:binds],
80
+ @options[:bind_to_activated_sockets] == 'only'
81
+ )
82
+ end
83
+
84
+ @log_writer.formatter = LogWriter::PidFormatter.new if clustered?
85
+ @log_writer.formatter = @options[:log_formatter] if @options[:log_formatter]
86
+
87
+ @log_writer.custom_logger = @options[:custom_logger] if @options[:custom_logger]
88
+
89
+ generate_restart_data
90
+
91
+ if clustered? && !Puma.forkable?
92
+ unsupported "worker mode not supported on #{RUBY_ENGINE} on this platform"
93
+ end
94
+
95
+ Dir.chdir(@restart_dir)
96
+
97
+ prune_bundler!
98
+
99
+ @environment = @options[:environment] if @options[:environment]
100
+ set_rack_environment
101
+
102
+ if clustered?
103
+ @runner = Cluster.new(self)
104
+ else
105
+ @runner = Single.new(self)
106
+ end
107
+ Puma.stats_object = @runner
108
+
109
+ @status = :run
110
+ end
111
+
112
+ attr_reader :binder, :log_writer, :events, :config, :options, :restart_dir
113
+
114
+ # Return stats about the server
115
+ def stats
116
+ @runner.stats
117
+ end
118
+
119
+ # Write a state file that can be used by pumactl to control
120
+ # the server
121
+ def write_state
122
+ write_pid
123
+
124
+ path = @options[:state]
125
+ permission = @options[:state_permission]
126
+ return unless path
127
+
128
+ require_relative 'state_file'
129
+
130
+ sf = StateFile.new
131
+ sf.pid = Process.pid
132
+ sf.control_url = @options[:control_url]
133
+ sf.control_auth_token = @options[:control_auth_token]
134
+ sf.running_from = File.expand_path('.')
135
+
136
+ sf.save path, permission
137
+ end
138
+
139
+ # Delete the configured pidfile
140
+ def delete_pidfile
141
+ path = @options[:pidfile]
142
+ File.unlink(path) if path && File.exist?(path)
143
+ end
144
+
145
+ # Begin async shutdown of the server
146
+ def halt
147
+ @status = :halt
148
+ @runner.halt
149
+ end
150
+
151
+ # Begin async shutdown of the server gracefully
152
+ def stop
153
+ @status = :stop
154
+ @runner.stop
155
+ end
156
+
157
+ # Begin async restart of the server
158
+ def restart
159
+ @status = :restart
160
+ @runner.restart
161
+ end
162
+
163
+ # Begin a phased restart if supported
164
+ def phased_restart
165
+ unless @runner.respond_to?(:phased_restart) and @runner.phased_restart
166
+ log "* phased-restart called but not available, restarting normally."
167
+ return restart
168
+ end
169
+
170
+ if @options.file_options[:tag].nil?
171
+ dir = File.realdirpath(@restart_dir)
172
+ @options[:tag] = File.basename(dir)
173
+ set_process_title
174
+ end
175
+
176
+ true
177
+ end
178
+
179
+ # Begin a refork if supported
180
+ def refork
181
+ if clustered? && @runner.respond_to?(:fork_worker!) && @options[:fork_worker]
182
+ @runner.fork_worker!
183
+ true
184
+ else
185
+ log "* refork called but not available."
186
+ false
187
+ end
188
+ end
189
+
190
+ # Run the server. This blocks until the server is stopped
191
+ def run
192
+ previous_env = get_env
193
+
194
+ @config.clamp
195
+
196
+ @config.plugins.fire_starts self
197
+
198
+ setup_signals
199
+ set_process_title
200
+
201
+ # This blocks until the server is stopped
202
+ @runner.run
203
+
204
+ do_run_finished(previous_env)
205
+ end
206
+
207
+ # Return all tcp ports the launcher may be using, TCP or SSL
208
+ # @!attribute [r] connected_ports
209
+ # @version 5.0.0
210
+ def connected_ports
211
+ @binder.connected_ports
212
+ end
213
+
214
+ # @!attribute [r] restart_args
215
+ def restart_args
216
+ cmd = @options[:restart_cmd]
217
+ if cmd
218
+ cmd.split(' ') + @original_argv
219
+ else
220
+ @restart_argv
221
+ end
222
+ end
223
+
224
+ def close_binder_listeners
225
+ @runner.close_control_listeners
226
+ @binder.close_listeners
227
+ unless @status == :restart
228
+ log "=== puma shutdown: #{Time.now} ==="
229
+ log "- Goodbye!"
230
+ end
231
+ end
232
+
233
+ # @!attribute [r] thread_status
234
+ # @version 5.0.0
235
+ def thread_status
236
+ Thread.list.each do |thread|
237
+ name = "Thread: TID-#{thread.object_id.to_s(36)}"
238
+ name += " #{thread['label']}" if thread['label']
239
+ name += " #{thread.name}" if thread.respond_to?(:name) && thread.name
240
+ backtrace = thread.backtrace || ["<no backtrace available>"]
241
+
242
+ yield name, backtrace
243
+ end
244
+ end
245
+
246
+ private
247
+
248
+ def get_env
249
+ if defined?(Bundler)
250
+ env = Bundler::ORIGINAL_ENV.dup
251
+ # add -rbundler/setup so we load from Gemfile when restarting
252
+ bundle = "-rbundler/setup"
253
+ env["RUBYOPT"] = [env["RUBYOPT"], bundle].join(" ").lstrip unless env["RUBYOPT"].to_s.include?(bundle)
254
+ env
255
+ else
256
+ ENV.to_h
257
+ end
258
+ end
259
+
260
+ def do_run_finished(previous_env)
261
+ case @status
262
+ when :halt
263
+ do_forceful_stop
264
+ when :run, :stop
265
+ do_graceful_stop
266
+ when :restart
267
+ do_restart(previous_env)
268
+ end
269
+
270
+ close_binder_listeners unless @status == :restart
271
+ end
272
+
273
+ def do_forceful_stop
274
+ log "* Stopping immediately!"
275
+ @runner.stop_control
276
+ end
277
+
278
+ def do_graceful_stop
279
+ @events.fire_after_stopped!
280
+ @runner.stop_blocked
281
+ end
282
+
283
+ def do_restart(previous_env)
284
+ log "* Restarting..."
285
+ ENV.replace(previous_env)
286
+ @runner.stop_control
287
+ restart!
288
+ end
289
+
290
+ def restart!
291
+ @events.fire_before_restart!
292
+ @config.run_hooks :before_restart, self, @log_writer
293
+
294
+ if Puma.jruby?
295
+ close_binder_listeners
296
+
297
+ require_relative 'jruby_restart'
298
+ argv = restart_args
299
+ JRubyRestart.chdir(@restart_dir)
300
+ Kernel.exec(*argv)
301
+ elsif Puma.windows?
302
+ close_binder_listeners
303
+
304
+ argv = restart_args
305
+ Dir.chdir(@restart_dir)
306
+ Kernel.exec(*argv)
307
+ else
308
+ argv = restart_args
309
+ Dir.chdir(@restart_dir)
310
+ ENV.update(@binder.redirects_for_restart_env)
311
+ argv += [@binder.redirects_for_restart]
312
+ Kernel.exec(*argv)
313
+ end
314
+ end
315
+
316
+ # If configured, write the pid of the current process out
317
+ # to a file.
318
+ def write_pid
319
+ path = @options[:pidfile]
320
+ return unless path
321
+ cur_pid = Process.pid
322
+ File.write path, cur_pid, mode: 'wb:UTF-8'
323
+ at_exit do
324
+ delete_pidfile if cur_pid == Process.pid
325
+ end
326
+ end
327
+
328
+ def reload_worker_directory
329
+ @runner.reload_worker_directory if @runner.respond_to?(:reload_worker_directory)
330
+ end
331
+
332
+ def log(str)
333
+ @log_writer.log(str)
334
+ end
335
+
336
+ def clustered?
337
+ (@options[:workers] || 0) > 0
338
+ end
339
+
340
+ def unsupported(str)
341
+ @log_writer.error(str)
342
+ raise UnsupportedOption
343
+ end
344
+
345
+ def set_process_title
346
+ Process.respond_to?(:setproctitle) ? Process.setproctitle(title) : $0 = title
347
+ end
348
+
349
+ # @!attribute [r] title
350
+ def title
351
+ buffer = "puma #{Puma::Const::VERSION} (#{@options[:binds].join(',')})"
352
+ buffer += " [#{@options[:tag]}]" if @options[:tag] && !@options[:tag].empty?
353
+ buffer
354
+ end
355
+
356
+ def set_rack_environment
357
+ @options[:environment] = environment
358
+ ENV['RACK_ENV'] = environment
359
+ end
360
+
361
+ # @!attribute [r] environment
362
+ def environment
363
+ @environment
364
+ end
365
+
366
+ def prune_bundler?
367
+ @options[:prune_bundler] && clustered? && !@options[:preload_app]
368
+ end
369
+
370
+ def prune_bundler!
371
+ return unless prune_bundler?
372
+ BundlePruner.new(@original_argv, @options[:extra_runtime_dependencies], @log_writer).prune
373
+ end
374
+
375
+ def generate_restart_data
376
+ if dir = @options[:directory]
377
+ @restart_dir = dir
378
+
379
+ elsif Puma.windows?
380
+ # I guess the value of PWD is garbage on windows so don't bother
381
+ # using it.
382
+ @restart_dir = Dir.pwd
383
+
384
+ # Use the same trick as unicorn, namely favor PWD because
385
+ # it will contain an unresolved symlink, useful for when
386
+ # the pwd is /data/releases/current.
387
+ elsif dir = ENV['PWD']
388
+ s_env = File.stat(dir)
389
+ s_pwd = File.stat(Dir.pwd)
390
+
391
+ if s_env.ino == s_pwd.ino and (Puma.jruby? or s_env.dev == s_pwd.dev)
392
+ @restart_dir = dir
393
+ end
394
+ end
395
+
396
+ @restart_dir ||= Dir.pwd
397
+
398
+ # if $0 is a file in the current directory, then restart
399
+ # it the same, otherwise add -S on there because it was
400
+ # picked up in PATH.
401
+ #
402
+ if File.exist?($0)
403
+ arg0 = [Gem.ruby, $0]
404
+ else
405
+ arg0 = [Gem.ruby, "-S", $0]
406
+ end
407
+
408
+ # Detect and reinject -Ilib from the command line, used for testing without bundler
409
+ # cruby has an expanded path, jruby has just "lib"
410
+ lib = File.expand_path "lib"
411
+ arg0[1,0] = ["-I", lib] if [lib, "lib"].include?($LOAD_PATH[0])
412
+
413
+ if defined? Puma::WILD_ARGS
414
+ @restart_argv = arg0 + Puma::WILD_ARGS + @original_argv
415
+ else
416
+ @restart_argv = arg0 + @original_argv
417
+ end
418
+ end
419
+
420
+ def setup_signals
421
+ unless ENV["PUMA_SKIP_SIGUSR2"]
422
+ begin
423
+ Signal.trap "SIGUSR2" do
424
+ restart
425
+ end
426
+ rescue Exception
427
+ log "*** SIGUSR2 not implemented, signal based restart unavailable!"
428
+ end
429
+ end
430
+
431
+ unless Puma.jruby?
432
+ begin
433
+ Signal.trap "SIGUSR1" do
434
+ phased_restart
435
+ end
436
+ rescue Exception
437
+ log "*** SIGUSR1 not implemented, signal based restart unavailable!"
438
+ end
439
+ end
440
+
441
+ begin
442
+ Signal.trap "SIGTERM" do
443
+ # Shortcut the control flow in case raise_exception_on_sigterm is true
444
+ do_graceful_stop
445
+
446
+ raise(SignalException, "SIGTERM") if @options[:raise_exception_on_sigterm]
447
+ end
448
+ rescue Exception
449
+ log "*** SIGTERM not implemented, signal based gracefully stopping unavailable!"
450
+ end
451
+
452
+ begin
453
+ Signal.trap "SIGINT" do
454
+ stop
455
+ end
456
+ rescue Exception
457
+ log "*** SIGINT not implemented, signal based gracefully stopping unavailable!"
458
+ end
459
+
460
+ begin
461
+ Signal.trap "SIGHUP" do
462
+ if @runner.redirected_io?
463
+ @runner.redirect_io
464
+ else
465
+ stop
466
+ end
467
+ end
468
+ rescue Exception
469
+ log "*** SIGHUP not implemented, signal based logs reopening unavailable!"
470
+ end
471
+
472
+ begin
473
+ unless Puma.jruby? # INFO in use by JVM already
474
+ Signal.trap "SIGINFO" do
475
+ thread_status do |name, backtrace|
476
+ @log_writer.log(name)
477
+ @log_writer.log(backtrace.map { |bt| " #{bt}" })
478
+ end
479
+ end
480
+ end
481
+ rescue Exception
482
+ # Not going to log this one, as SIGINFO is *BSD only and would be pretty annoying
483
+ # to see this constantly on Linux.
484
+ end
485
+ end
486
+
487
+ def log_config
488
+ log "Configuration:"
489
+
490
+ @config.final_options
491
+ .each { |config_key, value| log "- #{config_key}: #{value}" }
492
+
493
+ log "\n"
494
+ end
495
+ end
496
+ end
@@ -0,0 +1,147 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'null_io'
4
+ require_relative 'error_logger'
5
+ require 'stringio'
6
+ require 'io/wait' unless Puma::HAS_NATIVE_IO_WAIT
7
+
8
+ module Puma
9
+
10
+ # Handles logging concerns for both standard messages
11
+ # (+stdout+) and errors (+stderr+).
12
+ class LogWriter
13
+
14
+ class DefaultFormatter
15
+ def call(str)
16
+ str
17
+ end
18
+ end
19
+
20
+ class PidFormatter
21
+ def call(str)
22
+ "[#{$$}] #{str}"
23
+ end
24
+ end
25
+
26
+ LOG_QUEUE = Queue.new
27
+
28
+ attr_reader :stdout,
29
+ :stderr
30
+
31
+ attr_accessor :formatter, :custom_logger
32
+
33
+ # Create a LogWriter that prints to +stdout+ and +stderr+.
34
+ def initialize(stdout, stderr, env: ENV)
35
+ @formatter = DefaultFormatter.new
36
+ @custom_logger = nil
37
+ @stdout = stdout
38
+ @stderr = stderr
39
+
40
+ @debug = env.key?('PUMA_DEBUG')
41
+ @error_logger = ErrorLogger.new(@stderr, env: env)
42
+ end
43
+
44
+ DEFAULT = new(STDOUT, STDERR)
45
+
46
+ # Returns an LogWriter object which writes its status to
47
+ # two StringIO objects.
48
+ def self.strings(env: ENV)
49
+ LogWriter.new(StringIO.new, StringIO.new, env: env)
50
+ end
51
+
52
+ def self.stdio(env: ENV)
53
+ LogWriter.new($stdout, $stderr, env: env)
54
+ end
55
+
56
+ def self.null(env: ENV)
57
+ n = NullIO.new
58
+ LogWriter.new(n, n, env: env)
59
+ end
60
+
61
+ # Write +str+ to +@stdout+
62
+ def log(str)
63
+ if @custom_logger&.respond_to?(:write)
64
+ @custom_logger.write(format(str))
65
+ else
66
+ internal_write "#{@formatter.call str}\n"
67
+ end
68
+ end
69
+
70
+ def write(str)
71
+ internal_write @formatter.call(str)
72
+ end
73
+
74
+ def internal_write(str)
75
+ LOG_QUEUE << str
76
+ while (w_str = LOG_QUEUE.pop(true)) do
77
+ begin
78
+ @stdout.is_a?(IO) and @stdout.wait_writable(1)
79
+ @stdout.write w_str
80
+ @stdout.flush unless @stdout.sync
81
+ rescue Errno::EPIPE, Errno::EBADF, IOError, Errno::EINVAL
82
+ # 'Invalid argument' (Errno::EINVAL) may be raised by flush
83
+ end
84
+ end
85
+ rescue ThreadError
86
+ end
87
+ private :internal_write
88
+
89
+ def debug?
90
+ @debug
91
+ end
92
+
93
+ def debug(str)
94
+ log("% #{str}") if @debug
95
+ end
96
+
97
+ # Write +str+ to +@stderr+
98
+ def error(str)
99
+ @error_logger.info(text: @formatter.call("ERROR: #{str}"))
100
+ exit 1
101
+ end
102
+
103
+ def format(str)
104
+ formatter.call(str)
105
+ end
106
+
107
+ # An HTTP connection error has occurred.
108
+ # +error+ a connection exception, +req+ the request,
109
+ # and +text+ additional info
110
+ # @version 5.0.0
111
+ def connection_error(error, req, text="HTTP connection error")
112
+ @error_logger.info(error: error, req: req, text: text)
113
+ end
114
+
115
+ # An HTTP parse error has occurred.
116
+ # +error+ a parsing exception,
117
+ # and +req+ the request.
118
+ def parse_error(error, req)
119
+ @error_logger.info(error: error, req: req, text: 'HTTP parse error, malformed request')
120
+ end
121
+
122
+ # An SSL error has occurred.
123
+ # @param error <Puma::MiniSSL::SSLError>
124
+ # @param ssl_socket <Puma::MiniSSL::Socket>
125
+ def ssl_error(error, ssl_socket)
126
+ peeraddr = ssl_socket.peeraddr.last rescue "<unknown>"
127
+ peercert = ssl_socket.peercert
128
+ subject = peercert&.subject
129
+ @error_logger.info(error: error, text: "SSL error, peer: #{peeraddr}, peer cert: #{subject}")
130
+ end
131
+
132
+ # An unknown error has occurred.
133
+ # +error+ an exception object, +req+ the request,
134
+ # and +text+ additional info
135
+ def unknown_error(error, req=nil, text="Unknown error")
136
+ @error_logger.info(error: error, req: req, text: text)
137
+ end
138
+
139
+ # Log occurred error debug dump.
140
+ # +error+ an exception object, +req+ the request,
141
+ # and +text+ additional info
142
+ # @version 5.0.0
143
+ def debug_error(error, req=nil, text="")
144
+ @error_logger.debug(error: error, req: req, text: text)
145
+ end
146
+ end
147
+ end