[WIP] Refactor: Split out LogWriter from Events (no logic change) (#2798)

* Split out LogWriter from Events

* Improve code comment

* Fix constructor interfaces

* Fix file includes

* Fix specs and requires

* Fix LogWriter

* More fixes

* Fix tests

* Fix specs

* Fix spec

* Fix more specs

* Refactor: Split out LogWriter from Events

* Improve comments

* Fix bundle pruner

Co-authored-by: shields <shields@tablecheck.com>
This commit is contained in:
Johnny Shields 2022-02-06 02:06:22 +09:00 committed by GitHub
parent d7cfe19eb3
commit 8a4ef0c16c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
33 changed files with 556 additions and 539 deletions

View File

@ -8,8 +8,8 @@ app = proc {|env|
p env['puma.peercert']
[200, {}, [ env['puma.peercert'] ]]
}
events = Puma::Events.new($stdout, $stderr)
server = Puma::Server.new(app, events)
log_writer = Puma::LogWriter.new($stdout, $stderr)
server = Puma::Server.new(app, log_writer)
context = Puma::MiniSSL::Context.new
context.key = "certs/server.key"

View File

@ -28,8 +28,8 @@ module Puma
RACK_VERSION = [1,6].freeze
def initialize(events, conf = Configuration.new)
@events = events
def initialize(log_writer, conf = Configuration.new)
@log_writer = log_writer
@conf = conf
@listeners = []
@inherited_fds = {}
@ -38,7 +38,7 @@ module Puma
@proto_env = {
"rack.version".freeze => RACK_VERSION,
"rack.errors".freeze => events.stderr,
"rack.errors".freeze => log_writer.stderr,
"rack.multithread".freeze => conf.options[:max_threads] > 1,
"rack.multiprocess".freeze => conf.options[:workers] >= 1,
"rack.run_once".freeze => false,
@ -98,7 +98,7 @@ module Puma
# @version 5.0.0
#
def create_activated_fds(env_hash)
@events.debug "ENV['LISTEN_FDS'] #{ENV['LISTEN_FDS'].inspect} env_hash['LISTEN_PID'] #{env_hash['LISTEN_PID'].inspect}"
@log_writer.debug "ENV['LISTEN_FDS'] #{ENV['LISTEN_FDS'].inspect} env_hash['LISTEN_PID'] #{env_hash['LISTEN_PID'].inspect}"
return [] unless env_hash['LISTEN_FDS'] && env_hash['LISTEN_PID'].to_i == $$
env_hash['LISTEN_FDS'].to_i.times do |index|
sock = TCPServer.for_fd(socket_activation_fd(index))
@ -110,7 +110,7 @@ module Puma
[:tcp, addr, port]
end
@activated_sockets[key] = sock
@events.debug "Registered #{key.join ':'} for activation from LISTEN_FDS"
@log_writer.debug "Registered #{key.join ':'} for activation from LISTEN_FDS"
end
["LISTEN_FDS", "LISTEN_PID"] # Signal to remove these keys from ENV
end
@ -152,17 +152,17 @@ module Puma
end
end
def parse(binds, logger, log_msg = 'Listening')
def parse(binds, log_writer, log_msg = 'Listening')
binds.each do |str|
uri = URI.parse str
case uri.scheme
when "tcp"
if fd = @inherited_fds.delete(str)
io = inherit_tcp_listener uri.host, uri.port, fd
logger.log "* Inherited #{str}"
log_writer.log "* Inherited #{str}"
elsif sock = @activated_sockets.delete([ :tcp, uri.host, uri.port ])
io = inherit_tcp_listener uri.host, uri.port, sock
logger.log "* Activated #{str}"
log_writer.log "* Activated #{str}"
else
ios_len = @ios.length
params = Util.parse_query uri.query
@ -174,7 +174,7 @@ module Puma
@ios[ios_len..-1].each do |i|
addr = loc_addr_str i
logger.log "* #{log_msg} on http://#{addr}"
log_writer.log "* #{log_msg} on http://#{addr}"
end
end
@ -191,12 +191,12 @@ module Puma
if fd = @inherited_fds.delete(str)
@unix_paths << path unless abstract
io = inherit_unix_listener path, fd
logger.log "* Inherited #{str}"
log_writer.log "* Inherited #{str}"
elsif sock = @activated_sockets.delete([ :unix, path ]) ||
@activated_sockets.delete([ :unix, File.realdirpath(path) ])
@unix_paths << path unless abstract || File.exist?(path)
io = inherit_unix_listener path, sock
logger.log "* Activated #{str}"
log_writer.log "* Activated #{str}"
else
umask = nil
mode = nil
@ -220,7 +220,7 @@ module Puma
@unix_paths << path unless abstract || File.exist?(path)
io = add_unix_listener path, umask, mode, backlog
logger.log "* #{log_msg} on #{str}"
log_writer.log "* #{log_msg} on #{str}"
end
@listeners << [str, io]
@ -246,15 +246,15 @@ module Puma
params["#{v}_pem"] = @conf.options[:store][index]
end
end
MiniSSL::ContextBuilder.new(params, @events).context
MiniSSL::ContextBuilder.new(params, @log_writer).context
end
if fd = @inherited_fds.delete(str)
logger.log "* Inherited #{str}"
log_writer.log "* Inherited #{str}"
io = inherit_ssl_listener fd, ctx
elsif sock = @activated_sockets.delete([ :tcp, uri.host, uri.port ])
io = inherit_ssl_listener sock, ctx
logger.log "* Activated #{str}"
log_writer.log "* Activated #{str}"
else
ios_len = @ios.length
backlog = params.fetch('backlog', 1024).to_i
@ -262,20 +262,20 @@ module Puma
@ios[ios_len..-1].each do |i|
addr = loc_addr_str i
logger.log "* #{log_msg} on ssl://#{addr}?#{uri.query}"
log_writer.log "* #{log_msg} on ssl://#{addr}?#{uri.query}"
end
end
@listeners << [str, io] if io
else
logger.error "Invalid URI: #{str}"
log_writer.error "Invalid URI: #{str}"
end
end
# If we inherited fds but didn't use them (because of a
# configuration change), then be sure to close them.
@inherited_fds.each do |str, fd|
logger.log "* Closing unused inherited connection: #{str}"
log_writer.log "* Closing unused inherited connection: #{str}"
begin
IO.for_fd(fd).close
@ -295,7 +295,7 @@ module Puma
fds = @ios.map(&:to_i)
@activated_sockets.each do |key, sock|
next if fds.include? sock.to_i
logger.log "* Closing unused activated socket: #{key.first}://#{key[1..-1].join ':'}"
log_writer.log "* Closing unused activated socket: #{key.first}://#{key[1..-1].join ':'}"
begin
sock.close
rescue SystemCallError
@ -319,7 +319,7 @@ module Puma
local_certificates_path = File.expand_path("~/.localhost")
[File.join(local_certificates_path, "localhost.key"), File.join(local_certificates_path, "localhost.crt")]
end
MiniSSL::ContextBuilder.new({ "key" => key_path, "cert" => crt_path }, @events).context
MiniSSL::ContextBuilder.new({ "key" => key_path, "cert" => crt_path }, @log_writer).context
end
# Tell the server to listen on host +host+, port +port+.

View File

@ -7,7 +7,7 @@ require 'puma'
require 'puma/configuration'
require 'puma/launcher'
require 'puma/const'
require 'puma/events'
require 'puma/log_writer'
module Puma
class << self
@ -30,10 +30,10 @@ module Puma
# +stdout+ and +stderr+ can be set to IO-like objects which
# this object will report status on.
#
def initialize(argv, events=Events.stdio)
def initialize(argv, log_writer = LogWriter.stdio, events = Events.new)
@debug = false
@argv = argv.dup
@log_writer = log_writer
@events = events
@conf = nil
@ -69,7 +69,7 @@ module Puma
end
end
@launcher = Puma::Launcher.new(@conf, :events => @events, :argv => argv)
@launcher = Puma::Launcher.new(@conf, :log_writer => @log_writer, :events => @events, :argv => argv)
end
attr_reader :launcher
@ -83,7 +83,7 @@ module Puma
private
def unsupported(str)
@events.error(str)
@log_writer.error(str)
raise UnsupportedOption
end
@ -186,7 +186,7 @@ module Puma
end
o.on "-s", "--silent", "Do not log prompt messages other than errors" do
@events = Events.new NullIO.new, $stderr
@log_writer = LogWriter.new(NullIO.new, $stderr)
end
o.on "-S", "--state PATH", "Where to store the state details" do |arg|

View File

@ -17,8 +17,8 @@ module Puma
# via the `spawn_workers` method call. Each worker will have it's own
# instance of a `Puma::Server`.
class Cluster < Runner
def initialize(cli, events)
super cli, events
def initialize(launcher)
super(launcher)
@phase = 0
@workers = []
@ -96,7 +96,7 @@ module Puma
# @version 5.0.0
def spawn_worker(idx, master)
@launcher.config.run_hooks :before_worker_fork, idx, @launcher.events
@launcher.config.run_hooks(:before_worker_fork, idx, @launcher.log_writer)
pid = fork { worker(idx, master) }
if !pid
@ -105,7 +105,7 @@ module Puma
exit! 1
end
@launcher.config.run_hooks :after_worker_fork, idx, @launcher.events
@launcher.config.run_hooks(:after_worker_fork, idx, @launcher.log_writer)
pid
end
@ -413,8 +413,8 @@ module Puma
@master_read, @worker_write = read, @wakeup
@launcher.config.run_hooks :before_fork, nil, @launcher.events
Puma::Util.nakayoshi_gc @events if @options[:nakayoshi_fork]
@launcher.config.run_hooks(:before_fork, nil, @launcher.log_writer)
Puma::Util.nakayoshi_gc(@log_writer) if @options[:nakayoshi_fork]
spawn_workers

View File

@ -12,7 +12,7 @@ module Puma
attr_reader :index, :master
def initialize(index:, master:, launcher:, pipes:, server: nil)
super launcher, launcher.events
super(launcher)
@index = index
@master = master
@ -52,7 +52,7 @@ module Puma
# Invoke any worker boot hooks so they can get
# things in shape before booting the app.
@launcher.config.run_hooks :before_worker_boot, index, @launcher.events
@launcher.config.run_hooks(:before_worker_boot, index, @launcher.log_writer)
begin
server = @server ||= start_server
@ -83,8 +83,8 @@ module Puma
if restart_server.length > 0
restart_server.clear
server.begin_restart(true)
@launcher.config.run_hooks :before_refork, nil, @launcher.events
Puma::Util.nakayoshi_gc @events if @options[:nakayoshi_fork]
@launcher.config.run_hooks(:before_refork, nil, @launcher.log_writer)
Puma::Util.nakayoshi_gc(@log_writer) if @options[:nakayoshi_fork]
end
elsif idx == 0 # restart server
restart_server << true << false
@ -138,7 +138,7 @@ module Puma
# Invoke any worker shutdown hooks so they can prevent the worker
# exiting until any background operations are completed
@launcher.config.run_hooks :before_worker_shutdown, index, @launcher.events
@launcher.config.run_hooks(:before_worker_shutdown, index, @launcher.log_writer)
ensure
@worker_write << "t#{Process.pid}\n" rescue nil
@worker_write.close
@ -147,7 +147,7 @@ module Puma
private
def spawn_worker(idx)
@launcher.config.run_hooks :before_worker_fork, idx, @launcher.events
@launcher.config.run_hooks(:before_worker_fork, idx, @launcher.log_writer)
pid = fork do
new_worker = Worker.new index: idx,
@ -165,7 +165,7 @@ module Puma
exit! 1
end
@launcher.config.run_hooks :after_worker_fork, idx, @launcher.events
@launcher.config.run_hooks(:after_worker_fork, idx, @launcher.log_writer)
pid
end
end

View File

@ -291,13 +291,13 @@ module Puma
@plugins.create name
end
def run_hooks(key, arg, events)
def run_hooks(key, arg, log_writer)
@options.all_of(key).each do |b|
begin
b.call arg
rescue => e
events.log "WARNING hook #{key} failed with exception (#{e.class}) #{e.message}"
events.debug e.backtrace.join("\n")
log_writer.log "WARNING hook #{key} failed with exception (#{e.class}) #{e.message}"
log_writer.debug e.backtrace.join("\n")
end
end
end

View File

@ -293,13 +293,13 @@ module Puma
run_args += ["-C", @config_file] if @config_file
run_args += ["-e", @environment] if @environment
events = Puma::Events.new @stdout, @stderr
log_writer = Puma::LogWriter.new(@stdout, @stderr)
# replace $0 because puma use it to generate restart command
puma_cmd = $0.gsub(/pumactl$/, 'puma')
$0 = puma_cmd if File.exist?(puma_cmd)
cli = Puma::CLI.new run_args, events
cli = Puma::CLI.new run_args, log_writer
cli.run
end
end

View File

@ -1,52 +1,23 @@
# frozen_string_literal: true
require "puma/null_io"
require 'puma/error_logger'
require 'stringio'
module Puma
# The default implement of an event sink object used by Server
# for when certain kinds of events occur in the life of the server.
#
# The methods available are the events that the Server fires.
#
# This is an event sink used by `Puma::Server` to handle
# lifecycle events such as :on_booted, :on_restart, and :on_stopped.
# Using `Puma::DSL` it is possible to register callback hooks
# for each event type.
class Events
class DefaultFormatter
def call(str)
str
end
end
class PidFormatter
def call(str)
"[#{$$}] #{str}"
end
end
# Create an Events object that prints to +stdout+ and +stderr+.
#
def initialize(stdout, stderr)
@formatter = DefaultFormatter.new
@stdout = stdout
@stderr = stderr
@debug = ENV.key? 'PUMA_DEBUG'
@error_logger = ErrorLogger.new(@stderr)
def initialize
@hooks = Hash.new { |h,k| h[k] = [] }
end
attr_reader :stdout, :stderr
attr_accessor :formatter
# Fire callbacks for the named hook
#
def fire(hook, *args)
@hooks[hook].each { |t| t.call(*args) }
end
# Register a callback for a given hook
#
def register(hook, obj=nil, &blk)
if obj and blk
raise "Specify either an object or a block, not both"
@ -59,79 +30,6 @@ module Puma
h
end
# Write +str+ to +@stdout+
#
def log(str)
@stdout.puts format(str) if @stdout.respond_to? :puts
@stdout.flush unless @stdout.sync
rescue Errno::EPIPE
end
def write(str)
@stdout.write format(str)
end
def debug(str)
log("% #{str}") if @debug
end
# Write +str+ to +@stderr+
#
def error(str)
@error_logger.info(text: format("ERROR: #{str}"))
exit 1
end
def format(str)
formatter.call(str)
end
# An HTTP connection error has occurred.
# +error+ a connection exception, +req+ the request,
# and +text+ additional info
# @version 5.0.0
#
def connection_error(error, req, text="HTTP connection error")
@error_logger.info(error: error, req: req, text: text)
end
# An HTTP parse error has occurred.
# +error+ a parsing exception,
# and +req+ the request.
#
def parse_error(error, req)
@error_logger.info(error: error, req: req, text: 'HTTP parse error, malformed request')
end
# An SSL error has occurred.
# @param error <Puma::MiniSSL::SSLError>
# @param ssl_socket <Puma::MiniSSL::Socket>
#
def ssl_error(error, ssl_socket)
peeraddr = ssl_socket.peeraddr.last rescue "<unknown>"
peercert = ssl_socket.peercert
subject = peercert ? peercert.subject : nil
@error_logger.info(error: error, text: "SSL error, peer: #{peeraddr}, peer cert: #{subject}")
end
# An unknown error has occurred.
# +error+ an exception object, +req+ the request,
# and +text+ additional info
#
def unknown_error(error, req=nil, text="Unknown error")
@error_logger.info(error: error, req: req, text: text)
end
# Log occurred error debug dump.
# +error+ an exception object, +req+ the request,
# and +text+ additional info
# @version 5.0.0
#
def debug_error(error, req=nil, text="")
@error_logger.debug(error: error, req: req, text: text)
end
def on_booted(&block)
register(:on_booted, &block)
end
@ -155,23 +53,5 @@ module Puma
def fire_on_stopped!
fire(:on_stopped)
end
DEFAULT = new(STDOUT, STDERR)
# Returns an Events object which writes its status to 2 StringIO
# objects.
#
def self.strings
Events.new StringIO.new, StringIO.new
end
def self.stdio
Events.new $stdout, $stderr
end
def self.null
n = NullIO.new
Events.new n, n
end
end
end

View File

@ -1,5 +1,6 @@
# frozen_string_literal: true
require 'puma/log_writer'
require 'puma/events'
require 'puma/detect'
require 'puma/cluster'
@ -27,7 +28,7 @@ module Puma
# +conf+ A Puma::Configuration object indicating how to run the server.
#
# +launcher_args+ A Hash that currently has one required key `:events`,
# this is expected to hold an object similar to an `Puma::Events.stdio`,
# this is expected to hold an object similar to an `Puma::LogWriter.stdio`,
# this object will be responsible for broadcasting Puma's internal state
# to a logging destination. An optional key `:argv` can be supplied,
# this should be an array of strings, these arguments are re-used when
@ -41,15 +42,16 @@ module Puma
# [200, {}, ["hello world"]]
# end
# end
# Puma::Launcher.new(conf, events: Puma::Events.stdio).run
# Puma::Launcher.new(conf, log_writer: Puma::LogWriter.stdio).run
def initialize(conf, launcher_args={})
@runner = nil
@events = launcher_args[:events] || Events::DEFAULT
@log_writer = launcher_args[:log_writer] || LogWriter::DEFAULT
@events = launcher_args[:events] || Events.new
@argv = launcher_args[:argv] || []
@original_argv = @argv.dup
@config = conf
@binder = Binder.new(@events, conf)
@binder = Binder.new(@log_writer, conf)
@binder.create_inherited_fds(ENV).each { |k| ENV.delete k }
@binder.create_activated_fds(ENV).each { |k| ENV.delete k }
@ -70,8 +72,8 @@ module Puma
@options = @config.options
@config.clamp
@events.formatter = Events::PidFormatter.new if clustered?
@events.formatter = options[:log_formatter] if @options[:log_formatter]
@log_writer.formatter = LogWriter::PidFormatter.new if clustered?
@log_writer.formatter = options[:log_formatter] if @options[:log_formatter]
generate_restart_data
@ -87,11 +89,11 @@ module Puma
set_rack_environment
if clustered?
@options[:logger] = @events
@options[:logger] = @log_writer
@runner = Cluster.new(self, @events)
@runner = Cluster.new(self)
else
@runner = Single.new(self, @events)
@runner = Single.new(self)
end
Puma.stats_object = @runner
@ -100,7 +102,7 @@ module Puma
log_config if ENV['PUMA_LOG_CONFIG']
end
attr_reader :binder, :events, :config, :options, :restart_dir
attr_reader :binder, :log_writer, :events, :config, :options, :restart_dir
# Return stats about the server
def stats
@ -263,7 +265,7 @@ module Puma
def restart!
@events.fire_on_restart!
@config.run_hooks :on_restart, self, @events
@config.run_hooks :on_restart, self, @log_writer
if Puma.jruby?
close_binder_listeners
@ -317,13 +319,13 @@ module Puma
log "* Enabling systemd notification integration"
systemd = Systemd.new(@events)
systemd = Systemd.new(@log_writer, @events)
systemd.hook_events
systemd.start_watchdog
end
def log(str)
@events.log str
@log_writer.log(str)
end
def clustered?
@ -331,7 +333,7 @@ module Puma
end
def unsupported(str)
@events.error(str)
@log_writer.error(str)
raise UnsupportedOption
end
@ -362,7 +364,7 @@ module Puma
def prune_bundler!
return unless prune_bundler?
BundlePruner.new(@original_argv, @options[:extra_runtime_dependencies], @events).prune
BundlePruner.new(@original_argv, @options[:extra_runtime_dependencies], @log_writer).prune
end
def generate_restart_data
@ -464,8 +466,8 @@ module Puma
unless Puma.jruby? # INFO in use by JVM already
Signal.trap "SIGINFO" do
thread_status do |name, backtrace|
@events.log name
@events.log backtrace.map { |bt| " #{bt}" }
@log_writer.log(name)
@log_writer.log(backtrace.map { |bt| " #{bt}" })
end
end
end

View File

@ -7,10 +7,10 @@ module Puma
# application restarts.
class BundlePruner
def initialize(original_argv, extra_runtime_dependencies, events)
def initialize(original_argv, extra_runtime_dependencies, log_writer)
@original_argv = Array(original_argv)
@extra_runtime_dependencies = Array(extra_runtime_dependencies)
@events = events
@log_writer = log_writer
end
def prune
@ -96,7 +96,7 @@ module Puma
end
def log(str)
@events.log(str)
@log_writer.log(str)
end
end
end

123
lib/puma/log_writer.rb Normal file
View File

@ -0,0 +1,123 @@
# frozen_string_literal: true
require 'puma/null_io'
require 'puma/error_logger'
require 'stringio'
module Puma
# Handles logging concerns for both standard messages
# (+stdout+) and errors (+stderr+).
class LogWriter
class DefaultFormatter
def call(str)
str
end
end
class PidFormatter
def call(str)
"[#{$$}] #{str}"
end
end
attr_reader :stdout,
:stderr
attr_accessor :formatter
# Create a LogWriter that prints to +stdout+ and +stderr+.
def initialize(stdout, stderr)
@formatter = DefaultFormatter.new
@stdout = stdout
@stderr = stderr
@debug = ENV.key?('PUMA_DEBUG')
@error_logger = ErrorLogger.new(@stderr)
end
DEFAULT = new(STDOUT, STDERR)
# Returns an LogWriter object which writes its status to
# two StringIO objects.
def self.strings
LogWriter.new(StringIO.new, StringIO.new)
end
def self.stdio
LogWriter.new($stdout, $stderr)
end
def self.null
n = NullIO.new
LogWriter.new(n, n)
end
# Write +str+ to +@stdout+
def log(str)
@stdout.puts(format(str)) if @stdout.respond_to? :puts
@stdout.flush unless @stdout.sync
rescue Errno::EPIPE
end
def write(str)
@stdout.write(format(str))
end
def debug(str)
log("% #{str}") if @debug
end
# Write +str+ to +@stderr+
def error(str)
@error_logger.info(text: format("ERROR: #{str}"))
exit 1
end
def format(str)
formatter.call(str)
end
# An HTTP connection error has occurred.
# +error+ a connection exception, +req+ the request,
# and +text+ additional info
# @version 5.0.0
def connection_error(error, req, text="HTTP connection error")
@error_logger.info(error: error, req: req, text: text)
end
# An HTTP parse error has occurred.
# +error+ a parsing exception,
# and +req+ the request.
def parse_error(error, req)
@error_logger.info(error: error, req: req, text: 'HTTP parse error, malformed request')
end
# An SSL error has occurred.
# @param error <Puma::MiniSSL::SSLError>
# @param ssl_socket <Puma::MiniSSL::Socket>
def ssl_error(error, ssl_socket)
peeraddr = ssl_socket.peeraddr.last rescue "<unknown>"
peercert = ssl_socket.peercert
subject = peercert ? peercert.subject : nil
@error_logger.info(error: error, text: "SSL error, peer: #{peeraddr}, peer cert: #{subject}")
end
# An unknown error has occurred.
# +error+ an exception object, +req+ the request,
# and +text+ additional info
def unknown_error(error, req=nil, text="Unknown error")
@error_logger.info(error: error, req: req, text: text)
end
# Log occurred error debug dump.
# +error+ an exception object, +req+ the request,
# and +text+ additional info
# @version 5.0.0
def debug_error(error, req=nil, text="")
@error_logger.debug(error: error, req: req, text: text)
end
end
end

View File

@ -11,27 +11,27 @@ module Puma
if defined?(JRUBY_VERSION)
unless params['keystore']
events.error "Please specify the Java keystore via 'keystore='"
log_writer.error "Please specify the Java keystore via 'keystore='"
end
ctx.keystore = params['keystore']
unless params['keystore-pass']
events.error "Please specify the Java keystore password via 'keystore-pass='"
log_writer.error "Please specify the Java keystore password via 'keystore-pass='"
end
ctx.keystore_pass = params['keystore-pass']
ctx.ssl_cipher_list = params['ssl_cipher_list'] if params['ssl_cipher_list']
else
if params['key'].nil? && params['key_pem'].nil?
events.error "Please specify the SSL key via 'key=' or 'key_pem='"
log_writer.error "Please specify the SSL key via 'key=' or 'key_pem='"
end
ctx.key = params['key'] if params['key']
ctx.key_pem = params['key_pem'] if params['key_pem']
if params['cert'].nil? && params['cert_pem'].nil?
events.error "Please specify the SSL cert via 'cert=' or 'cert_pem='"
log_writer.error "Please specify the SSL cert via 'cert=' or 'cert_pem='"
end
ctx.cert = params['cert'] if params['cert']
@ -39,7 +39,7 @@ module Puma
if ['peer', 'force_peer'].include?(params['verify_mode'])
unless params['ca']
events.error "Please specify the SSL ca via 'ca='"
log_writer.error "Please specify the SSL ca via 'ca='"
end
end
@ -59,7 +59,7 @@ module Puma
when "none"
MiniSSL::VERIFY_NONE
else
events.error "Please specify a valid verify_mode="
log_writer.error "Please specify a valid verify_mode="
MiniSSL::VERIFY_NONE
end
end

View File

@ -58,7 +58,7 @@ module Puma
begin
fast_write io, str_early_hints(headers)
rescue ConnectionError => e
@events.debug_error e
@log_writer.debug_error e
# noop, if we lost the socket we just won't send the early hints
end
}
@ -89,12 +89,12 @@ module Puma
return :async
end
rescue ThreadPool::ForceShutdown => e
@events.unknown_error e, client, "Rack app"
@events.log "Detected force shutdown of a thread"
@log_writer.unknown_error e, client, "Rack app"
@log_writer.log "Detected force shutdown of a thread"
status, headers, res_body = lowlevel_error(e, env, 503)
rescue Exception => e
@events.unknown_error e, client, "Rack app"
@log_writer.unknown_error e, client, "Rack app"
status, headers, res_body = lowlevel_error(e, env, 500)
end

View File

@ -8,10 +8,11 @@ module Puma
# serve requests. This class spawns a new instance of `Puma::Server` via
# a call to `start_server`.
class Runner
def initialize(cli, events)
@launcher = cli
@events = events
@options = cli.options
def initialize(launcher)
@launcher = launcher
@log_writer = launcher.log_writer
@events = launcher.events
@options = launcher.options
@app = nil
@control = nil
@started_at = Time.now
@ -40,7 +41,7 @@ module Puma
end
def log(str)
@events.log str
@log_writer.log str
end
# @version 5.0.0
@ -49,11 +50,11 @@ module Puma
end
def error(str)
@events.error str
@log_writer.error str
end
def debug(str)
@events.log "- #{str}" if @options[:debug]
@log_writer.log "- #{str}" if @options[:debug]
end
def start_control
@ -68,7 +69,7 @@ module Puma
app = Puma::App::Status.new @launcher, token
control = Puma::Server.new app, @launcher.events,
control = Puma::Server.new app, @log_writer, @events,
{ min_threads: 0, max_threads: 1, queue_requests: false }
control.binder.parse [str], self, 'Starting control server'
@ -166,8 +167,8 @@ module Puma
end
def start_server
server = Puma::Server.new app, @launcher.events, @options
server.inherit_binder @launcher.binder
server = Puma::Server.new(app, @log_writer, @events, @options)
server.inherit_binder(@launcher.binder)
server
end

View File

@ -4,6 +4,7 @@ require 'stringio'
require 'puma/thread_pool'
require 'puma/const'
require 'puma/log_writer'
require 'puma/events'
require 'puma/null_io'
require 'puma/reactor'
@ -36,6 +37,7 @@ module Puma
extend Forwardable
attr_reader :thread
attr_reader :log_writer
attr_reader :events
attr_reader :min_threads, :max_threads # for #stats
attr_reader :requests_count # @version 5.0.0
@ -60,8 +62,9 @@ module Puma
# Create a server for the rack app +app+.
#
# +events+ is an object which will be called when certain error events occur
# to be handled. See Puma::Events for the list of current methods to implement.
# +log_writer+ is a Puma::LogWriter object used to log info and error messages.
#
# +events+ is a Puma::Events object used to notify application status events.
#
# Server#run returns a thread that you can join on to wait for the server
# to do its work.
@ -70,8 +73,9 @@ module Puma
# and have default values set via +fetch+. Normally the values are set via
# `::Puma::Configuration.puma_default_options`.
#
def initialize(app, events=Events.stdio, options={})
def initialize(app, log_writer=LogWriter.stdio, events=Events.new, options={})
@app = app
@log_writer = log_writer
@events = events
@check, @notify = nil
@ -97,7 +101,7 @@ module Puma
temp = !!(@options[:environment] =~ /\A(development|test)\z/)
@leak_stack_on_error = @options[:environment] ? temp : true
@binder = Binder.new(events)
@binder = Binder.new(log_writer)
ENV['RACK_ENV'] ||= "development"
@ -353,11 +357,11 @@ module Puma
# In the case that any of the sockets are unexpectedly close.
raise
rescue StandardError => e
@events.unknown_error e, nil, "Listen loop"
@log_writer.unknown_error e, nil, "Listen loop"
end
end
@events.debug "Drained #{drain} additional connections." if drain
@log_writer.debug "Drained #{drain} additional connections." if drain
@events.fire :state, @status
if queue_requests
@ -366,7 +370,7 @@ module Puma
end
graceful_shutdown if @status == :stop || @status == :restart
rescue Exception => e
@events.unknown_error e, nil, "Exception handling servers"
@log_writer.unknown_error e, nil, "Exception handling servers"
ensure
# RuntimeError is Ruby 2.2 issue, can't modify frozen IOError
# Errno::EBADF is infrequently raised
@ -488,7 +492,7 @@ module Puma
Puma::Util.purge_interrupt_queue
# Already closed
rescue StandardError => e
@events.unknown_error e, nil, "Client"
@log_writer.unknown_error e, nil, "Client"
end
end
end
@ -511,13 +515,13 @@ module Puma
lowlevel_error(e, client.env)
case e
when MiniSSL::SSLError
@events.ssl_error e, client.io
@log_writer.ssl_error e, client.io
when HttpParserError
client.write_error(400)
@events.parse_error e, client
@log_writer.parse_error e, client
else
client.write_error(500)
@events.unknown_error e, nil, "Read"
@log_writer.unknown_error e, nil, "Read"
end
end

View File

@ -4,7 +4,8 @@ require 'sd_notify'
module Puma
class Systemd
def initialize(events)
def initialize(log_writer, events)
@log_writer = log_writer
@events = events
end
@ -40,7 +41,7 @@ module Puma
end
def log(str)
@events.log str
@log_writer.log(str)
end
end
end

View File

@ -31,14 +31,14 @@ module Puma
module_function :unescape
# @version 5.0.0
def nakayoshi_gc(events)
events.log "! Promoting existing objects to old generation..."
def nakayoshi_gc(log_writer)
log_writer.log "! Promoting existing objects to old generation..."
4.times { GC.start(full_mark: false) }
if GC.respond_to?(:compact)
events.log "! Compacting..."
log_writer.log "! Compacting..."
GC.compact
end
events.log "! Friendly fork preparation complete."
log_writer.log "! Friendly fork preparation complete."
end
DEFAULT_SEP = /[&;] */n

View File

@ -13,7 +13,7 @@ module Rack
def self.config(app, options = {})
require 'puma'
require 'puma/configuration'
require 'puma/events'
require 'puma/log_writer'
require 'puma/launcher'
default_options = DEFAULT_OPTIONS.dup
@ -63,9 +63,9 @@ module Rack
def self.run(app, **options)
conf = self.config(app, options)
events = options.delete(:Silent) ? ::Puma::Events.strings : ::Puma::Events.stdio
log_writer = options.delete(:Silent) ? ::Puma::LogWriter.strings : ::Puma::LogWriter.stdio
launcher = ::Puma::Launcher.new(conf, :events => events)
launcher = ::Puma::Launcher.new(conf, :log_writer => log_writer)
yield launcher if block_given?
begin

View File

@ -33,8 +33,8 @@ require "puma/detect"
# used in various ssl test files, see test_puma_server_ssl.rb and
# test_puma_localhost_authority.rb
if Puma::HAS_SSL
require "puma/events"
class SSLEventsHelper < ::Puma::Events
require 'puma/log_writer'
class SSLLogWriterHelper < ::Puma::LogWriter
attr_accessor :addr, :cert, :error
def ssl_error(error, ssl_socket)

View File

@ -13,8 +13,8 @@ class TestBinderBase < Minitest::Test
include TmpPath
def setup
@events = Puma::Events.strings
@binder = Puma::Binder.new(@events)
@log_writer = Puma::LogWriter.strings
@binder = Puma::Binder.new(@log_writer)
end
def teardown
@ -80,14 +80,14 @@ class TestBinder < TestBinderBase
end
def test_localhost_addresses_dont_alter_listeners_for_tcp_addresses
@binder.parse ["tcp://localhost:0"], @events
@binder.parse ["tcp://localhost:0"], @log_writer
assert_empty @binder.listeners
end
def test_home_alters_listeners_for_tcp_addresses
port = UniquePort.call
@binder.parse ["tcp://127.0.0.1:#{port}"], @events
@binder.parse ["tcp://127.0.0.1:#{port}"], @log_writer
assert_equal "tcp://127.0.0.1:#{port}", @binder.listeners[0][0]
assert_kind_of TCPServer, @binder.listeners[0][1]
@ -96,14 +96,14 @@ class TestBinder < TestBinderBase
def test_connected_ports
ports = (1..3).map { |_| UniquePort.call }
@binder.parse(ports.map { |p| "tcp://localhost:#{p}" }, @events)
@binder.parse(ports.map { |p| "tcp://localhost:#{p}" }, @log_writer)
assert_equal ports, @binder.connected_ports
end
def test_localhost_addresses_dont_alter_listeners_for_ssl_addresses
skip_unless :ssl
@binder.parse ["ssl://localhost:0?#{ssl_query}"], @events
@binder.parse ["ssl://localhost:0?#{ssl_query}"], @log_writer
assert_empty @binder.listeners
end
@ -111,16 +111,16 @@ class TestBinder < TestBinderBase
def test_home_alters_listeners_for_ssl_addresses
skip_unless :ssl
port = UniquePort.call
@binder.parse ["ssl://127.0.0.1:#{port}?#{ssl_query}"], @events
@binder.parse ["ssl://127.0.0.1:#{port}?#{ssl_query}"], @log_writer
assert_equal "ssl://127.0.0.1:#{port}?#{ssl_query}", @binder.listeners[0][0]
assert_kind_of TCPServer, @binder.listeners[0][1]
end
def test_correct_zero_port
@binder.parse ["tcp://localhost:0"], @events
@binder.parse ["tcp://localhost:0"], @log_writer
m = %r!http://127.0.0.1:(\d+)!.match(@events.stdout.string)
m = %r!http://127.0.0.1:(\d+)!.match(@log_writer.stdout.string)
port = m[1].to_i
refute_equal 0, port
@ -131,30 +131,30 @@ class TestBinder < TestBinderBase
ssl_regex = %r!ssl://127.0.0.1:(\d+)!
@binder.parse ["ssl://localhost:0?#{ssl_query}"], @events
@binder.parse ["ssl://localhost:0?#{ssl_query}"], @log_writer
port = ssl_regex.match(@events.stdout.string)[1].to_i
port = ssl_regex.match(@log_writer.stdout.string)[1].to_i
refute_equal 0, port
end
def test_logs_all_localhost_bindings
@binder.parse ["tcp://localhost:0"], @events
@binder.parse ["tcp://localhost:0"], @log_writer
assert_match %r!http://127.0.0.1:(\d+)!, @events.stdout.string
assert_match %r!http://127.0.0.1:(\d+)!, @log_writer.stdout.string
if Socket.ip_address_list.any? {|i| i.ipv6_loopback? }
assert_match %r!http://\[::1\]:(\d+)!, @events.stdout.string
assert_match %r!http://\[::1\]:(\d+)!, @log_writer.stdout.string
end
end
def test_logs_all_localhost_bindings_ssl
skip_unless :ssl
@binder.parse ["ssl://localhost:0?#{ssl_query}"], @events
@binder.parse ["ssl://localhost:0?#{ssl_query}"], @log_writer
assert_match %r!ssl://127.0.0.1:(\d+)!, @events.stdout.string
assert_match %r!ssl://127.0.0.1:(\d+)!, @log_writer.stdout.string
if Socket.ip_address_list.any? {|i| i.ipv6_loopback? }
assert_match %r!ssl://\[::1\]:(\d+)!, @events.stdout.string
assert_match %r!ssl://\[::1\]:(\d+)!, @log_writer.stdout.string
end
end
@ -176,9 +176,9 @@ class TestBinder < TestBinderBase
unix_path = tmp_path('.sock')
File.open(unix_path, mode: 'wb') { |f| f.puts 'pre existing' }
@binder.parse ["unix://#{unix_path}"], @events
@binder.parse ["unix://#{unix_path}"], @log_writer
assert_match %r!unix://#{unix_path}!, @events.stdout.string
assert_match %r!unix://#{unix_path}!, @log_writer.stdout.string
refute_includes @binder.unix_paths, unix_path
@ -194,7 +194,7 @@ class TestBinder < TestBinderBase
def test_binder_parses_nil_low_latency
skip_if :jruby
@binder.parse ["tcp://0.0.0.0:0?low_latency"], @events
@binder.parse ["tcp://0.0.0.0:0?low_latency"], @log_writer
socket = @binder.listeners.first.last
@ -203,7 +203,7 @@ class TestBinder < TestBinderBase
def test_binder_parses_true_low_latency
skip_if :jruby
@binder.parse ["tcp://0.0.0.0:0?low_latency=true"], @events
@binder.parse ["tcp://0.0.0.0:0?low_latency=true"], @log_writer
socket = @binder.listeners.first.last
@ -212,7 +212,7 @@ class TestBinder < TestBinderBase
def test_binder_parses_false_low_latency
skip_if :jruby
@binder.parse ["tcp://0.0.0.0:0?low_latency=false"], @events
@binder.parse ["tcp://0.0.0.0:0?low_latency=false"], @log_writer
socket = @binder.listeners.first.last
@ -221,21 +221,21 @@ class TestBinder < TestBinderBase
def test_binder_parses_tlsv1_disabled
skip_unless :ssl
@binder.parse ["ssl://0.0.0.0:0?#{ssl_query}&no_tlsv1=true"], @events
@binder.parse ["ssl://0.0.0.0:0?#{ssl_query}&no_tlsv1=true"], @log_writer
assert ssl_context_for_binder.no_tlsv1
end
def test_binder_parses_tlsv1_enabled
skip_unless :ssl
@binder.parse ["ssl://0.0.0.0:0?#{ssl_query}&no_tlsv1=false"], @events
@binder.parse ["ssl://0.0.0.0:0?#{ssl_query}&no_tlsv1=false"], @log_writer
refute ssl_context_for_binder.no_tlsv1
end
def test_binder_parses_tlsv1_tlsv1_1_unspecified_defaults_to_enabled
skip_unless :ssl
@binder.parse ["ssl://0.0.0.0:0?#{ssl_query}"], @events
@binder.parse ["ssl://0.0.0.0:0?#{ssl_query}"], @log_writer
refute ssl_context_for_binder.no_tlsv1
refute ssl_context_for_binder.no_tlsv1_1
@ -243,21 +243,21 @@ class TestBinder < TestBinderBase
def test_binder_parses_tlsv1_1_disabled
skip_unless :ssl
@binder.parse ["ssl://0.0.0.0:0?#{ssl_query}&no_tlsv1_1=true"], @events
@binder.parse ["ssl://0.0.0.0:0?#{ssl_query}&no_tlsv1_1=true"], @log_writer
assert ssl_context_for_binder.no_tlsv1_1
end
def test_binder_parses_tlsv1_1_enabled
skip_unless :ssl
@binder.parse ["ssl://0.0.0.0:0?#{ssl_query}&no_tlsv1_1=false"], @events
@binder.parse ["ssl://0.0.0.0:0?#{ssl_query}&no_tlsv1_1=false"], @log_writer
refute ssl_context_for_binder.no_tlsv1_1
end
def test_env_contains_protoenv
skip_unless :ssl
@binder.parse ["ssl://localhost:0?#{ssl_query}"], @events
@binder.parse ["ssl://localhost:0?#{ssl_query}"], @log_writer
env_hash = @binder.envs[@binder.ios.first]
@ -268,11 +268,11 @@ class TestBinder < TestBinderBase
def test_env_contains_stderr
skip_unless :ssl
@binder.parse ["ssl://localhost:0?#{ssl_query}"], @events
@binder.parse ["ssl://localhost:0?#{ssl_query}"], @log_writer
env_hash = @binder.envs[@binder.ios.first]
assert_equal @events.stderr, env_hash["rack.errors"]
assert_equal @log_writer.stderr, env_hash["rack.errors"]
end
def test_ssl_binder_sets_backlog
@ -287,7 +287,7 @@ class TestBinder < TestBinderBase
end
TCPServer.stub(:new, tcp_server) do
@binder.parse ["ssl://#{host}:#{port}?#{ssl_query}&backlog=2048"], @events
@binder.parse ["ssl://#{host}:#{port}?#{ssl_query}&backlog=2048"], @log_writer
end
assert_equal 2048, Thread.current[:backlog]
@ -304,7 +304,7 @@ class TestBinder < TestBinderBase
end
def test_redirects_for_restart_creates_a_hash
@binder.parse ["tcp://127.0.0.1:0"], @events
@binder.parse ["tcp://127.0.0.1:0"], @log_writer
result = @binder.redirects_for_restart
ios = @binder.listeners.map { |_l, io| io.to_i }
@ -314,7 +314,7 @@ class TestBinder < TestBinderBase
end
def test_redirects_for_restart_env
@binder.parse ["tcp://127.0.0.1:0"], @events
@binder.parse ["tcp://127.0.0.1:0"], @log_writer
result = @binder.redirects_for_restart_env
@ -324,7 +324,7 @@ class TestBinder < TestBinderBase
end
def test_close_listeners_closes_ios
@binder.parse ["tcp://127.0.0.1:#{UniquePort.call}"], @events
@binder.parse ["tcp://127.0.0.1:#{UniquePort.call}"], @log_writer
refute @binder.listeners.any? { |_l, io| io.closed? }
@ -334,7 +334,7 @@ class TestBinder < TestBinderBase
end
def test_close_listeners_closes_ios_unless_closed?
@binder.parse ["tcp://127.0.0.1:0"], @events
@binder.parse ["tcp://127.0.0.1:0"], @log_writer
bomb = @binder.listeners.first[1]
bomb.close
@ -351,7 +351,7 @@ class TestBinder < TestBinderBase
skip_unless :unix
unix_path = tmp_path('.sock')
@binder.parse ["unix://#{unix_path}"], @events
@binder.parse ["unix://#{unix_path}"], @log_writer
assert File.socket?(unix_path)
@binder.close_listeners
@ -359,7 +359,7 @@ class TestBinder < TestBinderBase
end
def test_import_from_env_listen_inherit
@binder.parse ["tcp://127.0.0.1:0"], @events
@binder.parse ["tcp://127.0.0.1:0"], @log_writer
removals = @binder.create_inherited_fds(@binder.redirects_for_restart_env)
@binder.listeners.each do |l, io|
@ -399,7 +399,7 @@ class TestBinder < TestBinderBase
end
def test_rack_multithread_default_configuration
binder = Puma::Binder.new(@events)
binder = Puma::Binder.new(@log_writer)
assert binder.proto_env["rack.multithread"]
end
@ -407,13 +407,13 @@ class TestBinder < TestBinderBase
def test_rack_multithread_custom_configuration
conf = Puma::Configuration.new(max_threads: 1)
binder = Puma::Binder.new(@events, conf)
binder = Puma::Binder.new(@log_writer, conf)
refute binder.proto_env["rack.multithread"]
end
def test_rack_multiprocess_default_configuration
binder = Puma::Binder.new(@events)
binder = Puma::Binder.new(@log_writer)
refute binder.proto_env["rack.multiprocess"]
end
@ -421,7 +421,7 @@ class TestBinder < TestBinderBase
def test_rack_multiprocess_custom_configuration
conf = Puma::Configuration.new(workers: 1)
binder = Puma::Binder.new(@events, conf)
binder = Puma::Binder.new(@log_writer, conf)
assert binder.proto_env["rack.multiprocess"]
end
@ -430,7 +430,7 @@ class TestBinder < TestBinderBase
def assert_activates_sockets(path: nil, port: nil, url: nil, sock: nil)
hash = { "LISTEN_FDS" => 1, "LISTEN_PID" => $$ }
@events.instance_variable_set(:@debug, true)
@log_writer.instance_variable_set(:@debug, true)
@binder.instance_variable_set(:@sock_fd, sock.fileno)
def @binder.socket_activation_fd(int); @sock_fd; end
@ -440,7 +440,7 @@ class TestBinder < TestBinderBase
ary = path ? [:unix, path] : [:tcp, url, port]
assert_kind_of TCPServer, @binder.activated_sockets[ary]
assert_match "Registered #{ary.join(":")} for activation from LISTEN_FDS", @events.stdout.string
assert_match "Registered #{ary.join(":")} for activation from LISTEN_FDS", @log_writer.stdout.string
assert_equal ["LISTEN_FDS", "LISTEN_PID"], @result
end
@ -461,8 +461,8 @@ class TestBinder < TestBinderBase
tested_paths = [prepared_paths[order[0]], prepared_paths[order[1]]]
@binder.parse tested_paths, @events
stdout = @events.stdout.string
@binder.parse tested_paths, @log_writer
stdout = @log_writer.stdout.string
order.each do |prot|
assert_match expected_logs[prot], stdout
@ -479,7 +479,7 @@ class TestBinderJRuby < TestBinderBase
keystore = File.expand_path "../../examples/puma/keystore.jks", __FILE__
ssl_cipher_list = "TLS_DHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"
@binder.parse ["ssl://0.0.0.0:8080?#{ssl_query}"], @events
@binder.parse ["ssl://0.0.0.0:8080?#{ssl_query}"], @log_writer
assert_equal keystore, ssl_context_for_binder.keystore
assert_equal ssl_cipher_list, ssl_context_for_binder.ssl_cipher_list
@ -492,7 +492,7 @@ class TestBinderMRI < TestBinderBase
ssl_cipher_filter = "AES@STRENGTH"
@binder.parse ["ssl://0.0.0.0?#{ssl_query}&ssl_cipher_filter=#{ssl_cipher_filter}"], @events
@binder.parse ["ssl://0.0.0.0?#{ssl_query}&ssl_cipher_filter=#{ssl_cipher_filter}"], @log_writer
assert_equal ssl_cipher_filter, ssl_context_for_binder.ssl_cipher_filter
end
@ -502,7 +502,7 @@ class TestBinderMRI < TestBinderBase
input = "&verification_flags=TRUSTED_FIRST"
@binder.parse ["ssl://0.0.0.0?#{ssl_query}#{input}"], @events
@binder.parse ["ssl://0.0.0.0?#{ssl_query}#{input}"], @log_writer
assert_equal 0x8000, ssl_context_for_binder.verification_flags
end
@ -512,7 +512,7 @@ class TestBinderMRI < TestBinderBase
input = "&verification_flags=TRUSTED_FIRST,NO_CHECK_TIME"
@binder.parse ["ssl://0.0.0.0?#{ssl_query}#{input}"], @events
@binder.parse ["ssl://0.0.0.0?#{ssl_query}#{input}"], @log_writer
assert_equal 0x8000 | 0x200000, ssl_context_for_binder.verification_flags
end

View File

@ -52,6 +52,6 @@ class TestBundlePruner < Minitest::Test
private
def bundle_pruner(original_argv = nil, extra_runtime_dependencies = nil)
@bundle_pruner ||= Puma::Launcher::BundlePruner.new(original_argv, extra_runtime_dependencies, Puma::Events.null)
@bundle_pruner ||= Puma::Launcher::BundlePruner.new(original_argv, extra_runtime_dependencies, Puma::LogWriter.null)
end
end

View File

@ -53,7 +53,7 @@ class TestBusyWorker < Minitest::Test
end
end
@server = Puma::Server.new request_handler, Puma::Events.strings, **options
@server = Puma::Server.new request_handler, Puma::LogWriter.strings, Puma::Events.new, **options
@server.min_threads = options[:min_threads] || 0
@server.max_threads = options[:max_threads] || 10
@port = (@server.add_tcp_listener '127.0.0.1', 0).addr[1]

View File

@ -21,7 +21,9 @@ class TestCLI < Minitest::Test
@wait, @ready = IO.pipe
@events = Puma::Events.strings
@log_writer = Puma::LogWriter.strings
@events = Puma::Events.new
@events.on_booted { @ready << "!" }
end
@ -47,7 +49,7 @@ class TestCLI < Minitest::Test
cli = Puma::CLI.new ["-b", "tcp://127.0.0.1:0",
"--control-url", url,
"--control-token", "",
"test/rackup/lobster.ru"], @events
"test/rackup/lobster.ru"], @log_writer, @events
t = Thread.new do
cli.run
@ -82,7 +84,7 @@ class TestCLI < Minitest::Test
cli = Puma::CLI.new ["-b", "tcp://127.0.0.1:0",
"--control-url", control_url,
"--control-token", token,
"test/rackup/lobster.ru"], @events
"test/rackup/lobster.ru"], @log_writer, @events
t = Thread.new do
cli.run
@ -118,7 +120,7 @@ class TestCLI < Minitest::Test
"-w", "2",
"--control-url", url,
"--control-token", "",
"test/rackup/lobster.ru"], @events
"test/rackup/lobster.ru"], @log_writer, @events
# without this, Minitest.after_run will trigger on this test ?
$debugging_hold = true
@ -150,8 +152,8 @@ class TestCLI < Minitest::Test
done = nil
until done
@events.stdout.rewind
log = @events.stdout.readlines.join ''
@log_writer.stdout.rewind
log = @log_writer.stdout.readlines.join ''
done = log[/ - Goodbye!/]
end
@ -166,7 +168,7 @@ class TestCLI < Minitest::Test
cli = Puma::CLI.new ["-b", "unix://#{@tmp_path2}",
"--control-url", url,
"--control-token", "",
"test/rackup/lobster.ru"], @events
"test/rackup/lobster.ru"], @log_writer, @events
t = Thread.new { cli.run }
@ -193,7 +195,7 @@ class TestCLI < Minitest::Test
cli = Puma::CLI.new ["-b", "unix://#{@tmp_path2}",
"--control-url", url,
"--control-token", "",
"test/rackup/lobster.ru"], @events
"test/rackup/lobster.ru"], @log_writer, @events
t = Thread.new { cli.run }
@ -217,7 +219,7 @@ class TestCLI < Minitest::Test
cli = Puma::CLI.new ["-b", "tcp://127.0.0.1:#{tcp}",
"--control-url", url,
"--control-token", "",
"test/rackup/lobster.ru"], @events
"test/rackup/lobster.ru"], @log_writer, @events
t = Thread.new do
cli.run
@ -258,7 +260,7 @@ class TestCLI < Minitest::Test
cli = Puma::CLI.new ["-b", "unix://#{@tmp_path2}",
"--control-url", url,
"--control-token", "",
"test/rackup/lobster.ru"], @events
"test/rackup/lobster.ru"], @log_writer, @events
t = Thread.new { cli.run }
@ -279,7 +281,7 @@ class TestCLI < Minitest::Test
cli = Puma::CLI.new ["-b", uri,
"--control-url", cntl,
"--control-token", "",
"test/rackup/lobster.ru"], @events
"test/rackup/lobster.ru"], @log_writer, @events
t = Thread.new do
cli.run
@ -384,28 +386,28 @@ class TestCLI < Minitest::Test
def test_log_formatter_default_single
cli = Puma::CLI.new [ ]
assert_instance_of Puma::Events::DefaultFormatter, cli.launcher.events.formatter
assert_instance_of Puma::LogWriter::DefaultFormatter, cli.launcher.log_writer.formatter
end
def test_log_formatter_default_clustered
skip_unless :fork
cli = Puma::CLI.new [ "-w 2" ]
assert_instance_of Puma::Events::PidFormatter, cli.launcher.events.formatter
assert_instance_of Puma::LogWriter::PidFormatter, cli.launcher.log_writer.formatter
end
def test_log_formatter_custom_single
cli = Puma::CLI.new [ "--config", "test/config/custom_log_formatter.rb" ]
assert_instance_of Proc, cli.launcher.events.formatter
assert_match(/^\[.*\] \[.*\] .*: test$/, cli.launcher.events.format('test'))
assert_instance_of Proc, cli.launcher.log_writer.formatter
assert_match(/^\[.*\] \[.*\] .*: test$/, cli.launcher.log_writer.format('test'))
end
def test_log_formatter_custom_clustered
skip_unless :fork
cli = Puma::CLI.new [ "--config", "test/config/custom_log_formatter.rb", "-w 2" ]
assert_instance_of Proc, cli.launcher.events.formatter
assert_match(/^\[.*\] \[.*\] .*: test$/, cli.launcher.events.format('test'))
assert_instance_of Proc, cli.launcher.log_writer.formatter
assert_match(/^\[.*\] \[.*\] .*: test$/, cli.launcher.log_writer.format('test'))
end
def test_state
@ -480,10 +482,10 @@ class TestCLI < Minitest::Test
cli = Puma::CLI.new ['--silent']
cli.send(:setup_options)
events = cli.instance_variable_get(:@events)
log_writer = cli.instance_variable_get(:@log_writer)
assert_equal events.class, Puma::Events.null.class
assert_equal events.stdout.class, Puma::NullIO
assert_equal events.stderr, $stderr
assert_equal log_writer.class, Puma::LogWriter.null.class
assert_equal log_writer.stdout.class, Puma::NullIO
assert_equal log_writer.stderr, $stderr
end
end

View File

@ -4,7 +4,7 @@ require_relative "helper"
require_relative "helpers/config_file"
require "puma/configuration"
require 'puma/events'
require 'puma/log_writer'
class TestConfigFile < TestConfigFileBase
parallelize_me!
@ -373,11 +373,11 @@ class TestConfigFile < TestConfigFileBase
end
end
conf.load
events = Puma::Events.strings
log_writer = Puma::LogWriter.strings
conf.run_hooks :on_restart, 'ARG', events
conf.run_hooks(:on_restart, 'ARG', log_writer)
expected = /WARNING hook on_restart failed with exception \(RuntimeError\) Error from hook/
assert_match expected, events.stdout.string
assert_match expected, log_writer.stdout.string
end
def test_config_does_not_load_workers_by_default
@ -419,7 +419,7 @@ class TestConfigFile < TestConfigFileBase
messages << "#{hook_name} is called with #{a}"
}
conf.run_hooks hook_name, 'ARG', Puma::Events.strings
conf.run_hooks(hook_name, 'ARG', Puma::LogWriter.strings)
assert_equal messages, ["#{hook_name} is called with ARG"]
# test multiple
@ -435,7 +435,7 @@ class TestConfigFile < TestConfigFileBase
end
conf.load
conf.run_hooks hook_name, 'ARG', Puma::Events.strings
conf.run_hooks(hook_name, 'ARG', Puma::LogWriter.strings)
assert_equal messages, ["#{hook_name} is called with ARG one time", "#{hook_name} is called with ARG a second time"]
end
end

View File

@ -2,41 +2,10 @@ require 'puma/events'
require_relative "helper"
class TestEvents < Minitest::Test
def test_null
events = Puma::Events.null
assert_instance_of Puma::NullIO, events.stdout
assert_instance_of Puma::NullIO, events.stderr
assert_equal events.stdout, events.stderr
end
def test_strings
events = Puma::Events.strings
assert_instance_of StringIO, events.stdout
assert_instance_of StringIO, events.stderr
end
def test_stdio
events = Puma::Events.stdio
assert_equal STDOUT, events.stdout
assert_equal STDERR, events.stderr
end
def test_stdio_respects_sync
events = Puma::Events.stdio
assert_equal STDOUT.sync, events.stdout.sync
assert_equal STDERR.sync, events.stderr.sync
assert_equal STDOUT, events.stdout
assert_equal STDERR, events.stderr
end
def test_register_callback_with_block
res = false
events = Puma::Events.null
events = Puma::Events.new
events.register(:exec) { res = true }
@ -56,7 +25,7 @@ class TestEvents < Minitest::Test
@res = true
end
events = Puma::Events.null
events = Puma::Events.new
events.register(:exec, obj)
@ -68,7 +37,7 @@ class TestEvents < Minitest::Test
def test_fire_callback_with_multiple_arguments
res = []
events = Puma::Events.null
events = Puma::Events.new
events.register(:exec) { |*args| res.concat(args) }
@ -80,7 +49,7 @@ class TestEvents < Minitest::Test
def test_on_booted_callback
res = false
events = Puma::Events.null
events = Puma::Events.new
events.on_booted { res = true }
@ -88,151 +57,4 @@ class TestEvents < Minitest::Test
assert res
end
def test_log_writes_to_stdout
out, _ = capture_io do
Puma::Events.stdio.log("ready")
end
assert_equal "ready\n", out
end
def test_null_log_does_nothing
out, _ = capture_io do
Puma::Events.null.log("ready")
end
assert_equal "", out
end
def test_write_writes_to_stdout
out, _ = capture_io do
Puma::Events.stdio.write("ready")
end
assert_equal "ready", out
end
def test_debug_writes_to_stdout_if_env_is_present
original_debug, ENV["PUMA_DEBUG"] = ENV["PUMA_DEBUG"], "1"
out, _ = capture_io do
Puma::Events.stdio.debug("ready")
end
assert_equal "% ready\n", out
ensure
ENV["PUMA_DEBUG"] = original_debug
end
def test_debug_not_write_to_stdout_if_env_is_not_present
out, _ = capture_io do
Puma::Events.stdio.debug("ready")
end
assert_empty out
end
def test_error_writes_to_stderr_and_exits
did_exit = false
_, err = capture_io do
begin
Puma::Events.stdio.error("interrupted")
rescue SystemExit
did_exit = true
ensure
assert did_exit
end
end
assert_match %r!ERROR: interrupted!, err
end
def test_pid_formatter
pid = Process.pid
out, _ = capture_io do
events = Puma::Events.stdio
events.formatter = Puma::Events::PidFormatter.new
events.write("ready")
end
assert_equal "[#{ pid }] ready", out
end
def test_custom_log_formatter
custom_formatter = proc { |str| "-> #{ str }" }
out, _ = capture_io do
events = Puma::Events.stdio
events.formatter = custom_formatter
events.write("ready")
end
assert_equal "-> ready", out
end
def test_parse_error
port = 0
host = "127.0.0.1"
app = proc { |env| [200, {"Content-Type" => "plain/text"}, ["hello\n"]] }
events = Puma::Events.strings
server = Puma::Server.new app, events
port = (server.add_tcp_listener host, 0).addr[1]
server.run
sock = TCPSocket.new host, port
path = "/"
params = "a"*1024*10
sock << "GET #{path}?a=#{params} HTTP/1.1\r\nConnection: close\r\n\r\n"
sock.read
sleep 0.1 # important so that the previous data is sent as a packet
assert_match %r!HTTP parse error, malformed request!, events.stderr.string
assert_match %r!\("GET #{path}" - \(-\)\)!, events.stderr.string
ensure
sock.close if sock && !sock.closed?
server.stop true
end
# test_puma_server_ssl.rb checks that ssl errors are raised correctly,
# but it mocks the actual error code. This test the code, but it will
# break if the logged message changes
def test_ssl_error
events = Puma::Events.strings
ssl_mock = -> (addr, subj) {
obj = Object.new
obj.define_singleton_method(:peeraddr) { addr }
if subj
cert = Object.new
cert.define_singleton_method(:subject) { subj }
obj.define_singleton_method(:peercert) { cert }
else
obj.define_singleton_method(:peercert) { nil }
end
obj
}
events.ssl_error OpenSSL::SSL::SSLError, ssl_mock.call(['127.0.0.1'], 'test_cert')
error = events.stderr.string
assert_includes error, "SSL error"
assert_includes error, "peer: 127.0.0.1"
assert_includes error, "cert: test_cert"
events.stderr.string = ''
events.ssl_error OpenSSL::SSL::SSLError, ssl_mock.call(nil, nil)
error = events.stderr.string
assert_includes error, "SSL error"
assert_includes error, "peer: <unknown>"
assert_includes error, "cert: :"
end if ::Puma::HAS_SSL
end

View File

@ -2,7 +2,7 @@ require_relative "helper"
require_relative "helpers/tmp_path"
require "puma/configuration"
require 'puma/events'
require 'puma/log_writer'
class TestLauncher < Minitest::Test
include TmpPath
@ -112,17 +112,17 @@ class TestLauncher < Minitest::Test
def test_log_config_enabled
ENV['PUMA_LOG_CONFIG'] = "1"
assert_match(/Configuration:/, launcher.events.stdout.string)
assert_match(/Configuration:/, launcher.log_writer.stdout.string)
launcher.config.final_options.each do |config_key, _value|
assert_match(/#{config_key}/, launcher.events.stdout.string)
assert_match(/#{config_key}/, launcher.log_writer.stdout.string)
end
ENV.delete('PUMA_LOG_CONFIG')
end
def test_log_config_disabled
refute_match(/Configuration:/, launcher.events.stdout.string)
refute_match(/Configuration:/, launcher.log_writer.stdout.string)
end
def test_fire_on_stopped
@ -147,11 +147,11 @@ class TestLauncher < Minitest::Test
private
def events
@events ||= Puma::Events.strings
def log_writer
@log_writer ||= Puma::LogWriter.strings
end
def launcher(config = Puma::Configuration.new, evts = events)
@launcher ||= Puma::Launcher.new(config, events: evts)
def launcher(config = Puma::Configuration.new, lw = log_writer)
@launcher ||= Puma::Launcher.new(config, log_writer: lw)
end
end

181
test/test_log_writer.rb Normal file
View File

@ -0,0 +1,181 @@
require 'puma/log_writer'
require_relative "helper"
class TestLogWriter < Minitest::Test
def test_null
log_writer = Puma::LogWriter.null
assert_instance_of Puma::NullIO, log_writer.stdout
assert_instance_of Puma::NullIO, log_writer.stderr
assert_equal log_writer.stdout, log_writer.stderr
end
def test_strings
log_writer = Puma::LogWriter.strings
assert_instance_of StringIO, log_writer.stdout
assert_instance_of StringIO, log_writer.stderr
end
def test_stdio
log_writer = Puma::LogWriter.stdio
assert_equal STDOUT, log_writer.stdout
assert_equal STDERR, log_writer.stderr
end
def test_stdio_respects_sync
log_writer = Puma::LogWriter.stdio
assert_equal STDOUT.sync, log_writer.stdout.sync
assert_equal STDERR.sync, log_writer.stderr.sync
assert_equal STDOUT, log_writer.stdout
assert_equal STDERR, log_writer.stderr
end
def test_log_writes_to_stdout
out, _ = capture_io do
Puma::LogWriter.stdio.log("ready")
end
assert_equal "ready\n", out
end
def test_null_log_does_nothing
out, _ = capture_io do
Puma::LogWriter.null.log("ready")
end
assert_equal "", out
end
def test_write_writes_to_stdout
out, _ = capture_io do
Puma::LogWriter.stdio.write("ready")
end
assert_equal "ready", out
end
def test_debug_writes_to_stdout_if_env_is_present
original_debug, ENV["PUMA_DEBUG"] = ENV["PUMA_DEBUG"], "1"
out, _ = capture_io do
Puma::LogWriter.stdio.debug("ready")
end
assert_equal "% ready\n", out
ensure
ENV["PUMA_DEBUG"] = original_debug
end
def test_debug_not_write_to_stdout_if_env_is_not_present
out, _ = capture_io do
Puma::LogWriter.stdio.debug("ready")
end
assert_empty out
end
def test_error_writes_to_stderr_and_exits
did_exit = false
_, err = capture_io do
begin
Puma::LogWriter.stdio.error("interrupted")
rescue SystemExit
did_exit = true
ensure
assert did_exit
end
end
assert_match %r!ERROR: interrupted!, err
end
def test_pid_formatter
pid = Process.pid
out, _ = capture_io do
log_writer = Puma::LogWriter.stdio
log_writer.formatter = Puma::LogWriter::PidFormatter.new
log_writer.write("ready")
end
assert_equal "[#{ pid }] ready", out
end
def test_custom_log_formatter
custom_formatter = proc { |str| "-> #{ str }" }
out, _ = capture_io do
log_writer = Puma::LogWriter.stdio
log_writer.formatter = custom_formatter
log_writer.write("ready")
end
assert_equal "-> ready", out
end
def test_parse_error
app = proc { |_env| [200, {"Content-Type" => "plain/text"}, ["hello\n"]] }
log_writer = Puma::LogWriter.strings
server = Puma::Server.new app, log_writer
host = '127.0.0.1'
port = (server.add_tcp_listener host, 0).addr[1]
server.run
sock = TCPSocket.new host, port
path = "/"
params = "a"*1024*10
sock << "GET #{path}?a=#{params} HTTP/1.1\r\nConnection: close\r\n\r\n"
sock.read
sleep 0.1 # important so that the previous data is sent as a packet
assert_match %r!HTTP parse error, malformed request!, log_writer.stderr.string
assert_match %r!\("GET #{path}" - \(-\)\)!, log_writer.stderr.string
ensure
sock.close if sock && !sock.closed?
server.stop true
end
# test_puma_server_ssl.rb checks that ssl errors are raised correctly,
# but it mocks the actual error code. This test the code, but it will
# break if the logged message changes
def test_ssl_error
log_writer = Puma::LogWriter.strings
ssl_mock = -> (addr, subj) {
obj = Object.new
obj.define_singleton_method(:peeraddr) { addr }
if subj
cert = Object.new
cert.define_singleton_method(:subject) { subj }
obj.define_singleton_method(:peercert) { cert }
else
obj.define_singleton_method(:peercert) { nil }
end
obj
}
log_writer.ssl_error OpenSSL::SSL::SSLError, ssl_mock.call(['127.0.0.1'], 'test_cert')
error = log_writer.stderr.string
assert_includes error, "SSL error"
assert_includes error, "peer: 127.0.0.1"
assert_includes error, "cert: test_cert"
log_writer.stderr.string = ''
log_writer.ssl_error OpenSSL::SSL::SSLError, ssl_mock.call(nil, nil)
error = log_writer.stderr.string
assert_includes error, "SSL error"
assert_includes error, "peer: <unknown>"
assert_includes error, "cert: :"
end if ::Puma::HAS_SSL
end

View File

@ -59,7 +59,7 @@ class TestOutOfBandServer < Minitest::Test
[200, {}, [""]]
end
@server = Puma::Server.new app, Puma::Events.strings, out_of_band: [oob], **options
@server = Puma::Server.new app, Puma::LogWriter.strings, Puma::Events.new, out_of_band: [oob], **options
@server.min_threads = options[:min_threads] || 1
@server.max_threads = options[:max_threads] || 1
@port = (@server.add_tcp_listener '127.0.0.1', 0).addr[1]

View File

@ -30,8 +30,8 @@ class TestPumaLocalhostAuthority < Minitest::Test
@host = "localhost"
app = lambda { |env| [200, {}, [env['rack.url_scheme']]] }
@events = SSLEventsHelper.new STDOUT, STDERR
@server = Puma::Server.new app, @events
@log_writer = SSLLogWriterHelper.new STDOUT, STDERR
@server = Puma::Server.new app, @log_writer
@server.app = app
@server.add_ssl_listener @host, 0,nil
@http = Net::HTTP.new @host, @server.connected_ports[0]
@ -61,9 +61,9 @@ class TestPumaSSLLocalhostAuthority < Minitest::Test
app = lambda { |env| [200, {}, [env['rack.url_scheme']]] }
@events = SSLEventsHelper.new STDOUT, STDERR
@log_writer = SSLLogWriterHelper.new STDOUT, STDERR
@server = Puma::Server.new app, @events
@server = Puma::Server.new app, @log_writer
@server.app = app
@server.add_ssl_listener @host, 0,nil

View File

@ -14,8 +14,9 @@ class TestPumaServer < Minitest::Test
@app = ->(env) { [200, {}, [env['rack.url_scheme']]] }
@events = Puma::Events.strings
@server = Puma::Server.new @app, @events
@log_writer = Puma::LogWriter.strings
@events = Puma::Events.new
@server = Puma::Server.new @app, @log_writer, @events
end
def teardown
@ -24,7 +25,7 @@ class TestPumaServer < Minitest::Test
end
def server_run(**options, &block)
@server = Puma::Server.new block || @app, @events, options
@server = Puma::Server.new block || @app, @log_writer, @events, options
@port = (@server.add_tcp_listener @host, 0).addr[1]
@server.run
sleep 0.15 if Puma.jruby?
@ -296,7 +297,7 @@ EOF
sleep 0.1
# Expect no errors in stderr
assert @events.stderr.pos.zero?, "Server didn't swallow the connection error"
assert @log_writer.stderr.pos.zero?, "Server didn't swallow the connection error"
end
def test_early_hints_is_off_by_default
@ -341,7 +342,7 @@ EOF
new_connection.close # Make a connection and close without writing
@server.stop(true)
stderr = @events.stderr.string
stderr = @log_writer.stderr.string
assert stderr.empty?, "Expected stderr from server to be empty but it was #{stderr.inspect}"
end
@ -361,7 +362,7 @@ EOF
def test_lowlevel_error_message
skip_if :windows
@server = Puma::Server.new @app, @events, {:force_shutdown_after => 2}
@server = Puma::Server.new @app, @log_writer, @events, {:force_shutdown_after => 2}
server_run do
if TestSkips::TRUFFLE
@ -508,7 +509,7 @@ EOF
end
def test_no_timeout_after_data_received_no_queue
@server = Puma::Server.new @app, @events, queue_requests: false
@server = Puma::Server.new @app, @log_writer, @events, queue_requests: false
test_no_timeout_after_data_received
end
@ -1244,7 +1245,7 @@ EOF
# System-resource errors such as EMFILE should not be silently swallowed by accept loop.
def test_accept_emfile
stub_accept_nonblock Errno::EMFILE.new('accept(2)')
refute_empty @events.stderr.string, "Expected EMFILE error not logged"
refute_empty @log_writer.stderr.string, "Expected EMFILE error not logged"
end
# Retryable errors such as ECONNABORTED should be silently swallowed by accept loop.
@ -1252,7 +1253,7 @@ EOF
# Match Ruby #accept_nonblock implementation, ECONNABORTED error is extended by IO::WaitReadable.
error = Errno::ECONNABORTED.new('accept(2) would block').tap {|e| e.extend IO::WaitReadable}
stub_accept_nonblock(error)
assert_empty @events.stderr.string
assert_empty @log_writer.stderr.string
end
# see https://github.com/puma/puma/issues/2390
@ -1260,7 +1261,7 @@ EOF
#
def test_client_quick_close_no_lowlevel_error_handler_call
handler = ->(err, env, status) {
@events.stdout.write "LLEH #{err.message}"
@log_writer.stdout.write "LLEH #{err.message}"
[500, {"Content-Type" => "application/json"}, ["{}\n"]]
}
@ -1274,21 +1275,21 @@ EOF
sock.close
assert_match 'Hello World', resp
sleep 0.5
assert_empty @events.stdout.string
assert_empty @log_writer.stdout.string
# valid req, close
sock = TCPSocket.new @host, @port
sock.syswrite "GET / HTTP/1.0\r\n\r\n"
sock.close
sleep 0.5
assert_empty @events.stdout.string
assert_empty @log_writer.stdout.string
# invalid req, close
sock = TCPSocket.new @host, @port
sock.syswrite "GET / HTTP"
sock.close
sleep 0.5
assert_empty @events.stdout.string
assert_empty @log_writer.stdout.string
end
def test_idle_connections_closed_immediately_on_shutdown
@ -1325,7 +1326,7 @@ EOF
def test_custom_io_selector
backend = NIO::Selector.backends.first
@server = Puma::Server.new @app, @events, {:io_selector_backend => backend}
@server = Puma::Server.new @app, @log_writer, @events, {:io_selector_backend => backend}
@server.run
selector = @server.instance_variable_get(:@reactor).instance_variable_get(:@selector)
@ -1374,9 +1375,9 @@ EOF
@port = UniquePort.call
opts = { rack_url_scheme: 'user', binds: ["tcp://#{@host}:#{@port}"] }
conf = Puma::Configuration.new(opts).tap(&:clamp)
@server = Puma::Server.new @app, @events, conf.options
@server.inherit_binder Puma::Binder.new(@events, conf)
@server.binder.parse conf.options[:binds], @events
@server = Puma::Server.new @app, @log_writer, @events, conf.options
@server.inherit_binder Puma::Binder.new(@log_writer, conf)
@server.binder.parse conf.options[:binds], @log_writer
@server.run
data = send_http_and_read "GET / HTTP/1.0\r\n\r\n"

View File

@ -55,8 +55,8 @@ class TestPumaServerSSL < Minitest::Test
yield ctx if block_given?
@events = SSLEventsHelper.new STDOUT, STDERR
@server = Puma::Server.new app, @events
@log_writer = SSLLogWriterHelper.new STDOUT, STDERR
@server = Puma::Server.new app, @log_writer
@port = (@server.add_ssl_listener @host, 0, ctx).addr[1]
@server.run
@ -148,7 +148,7 @@ class TestPumaServerSSL < Minitest::Test
end
unless Puma.jruby?
msg = /wrong version number|no protocols available|version too low|unknown SSL method/
assert_match(msg, @events.error.message) if @events.error
assert_match(msg, @log_writer.error.message) if @log_writer.error
end
end
@ -169,7 +169,7 @@ class TestPumaServerSSL < Minitest::Test
end
unless Puma.jruby?
msg = /wrong version number|(unknown|unsupported) protocol|no protocols available|version too low|unknown SSL method/
assert_match(msg, @events.error.message) if @events.error
assert_match(msg, @log_writer.error.message) if @log_writer.error
end
end
@ -189,7 +189,7 @@ class TestPumaServerSSL < Minitest::Test
end
unless Puma.jruby?
msg = /wrong version number|(unknown|unsupported) protocol|no protocols available|version too low|unknown SSL method/
assert_match(msg, @events.error.message) if @events.error
assert_match(msg, @log_writer.error.message) if @log_writer.error
end
end
@ -258,8 +258,8 @@ class TestPumaServerSSLClient < Minitest::Test
app = lambda { |env| [200, {}, [env['rack.url_scheme']]] }
events = SSLEventsHelper.new STDOUT, STDERR
server = Puma::Server.new app, events
log_writer = SSLLogWriterHelper.new STDOUT, STDERR
server = Puma::Server.new app, log_writer
server.add_ssl_listener host, port, CTX
host_addrs = server.binder.ios.map { |io| io.to_io.addr[2] }
server.run
@ -288,9 +288,9 @@ class TestPumaServerSSLClient < Minitest::Test
# The JRuby MiniSSL implementation lacks error capturing currently,
# so we can't inspect the messages here
unless Puma.jruby?
assert_match error, events.error.message if error
assert_includes host_addrs, events.addr if error
assert_equal subject, events.cert.subject.to_s if subject
assert_match error, log_writer.error.message if error
assert_includes host_addrs, log_writer.addr if error
assert_equal subject, log_writer.cert.subject.to_s if subject
end
ensure
server.stop(true) if server
@ -346,8 +346,8 @@ class TestPumaServerSSLWithCertPemAndKeyPem < Minitest::Test
}
app = lambda { |env| [200, {}, [env['rack.url_scheme']]] }
events = SSLEventsHelper.new STDOUT, STDERR
server = Puma::Server.new app, events
log_writer = SSLLogWriterHelper.new STDOUT, STDERR
server = Puma::Server.new app, log_writer
server.add_ssl_listener host, port, ctx
server.run

View File

@ -12,8 +12,8 @@ class TestResponseHeader < Minitest::Test
@app = ->(env) { [200, {}, [env['rack.url_scheme']]] }
@events = Puma::Events.strings
@server = Puma::Server.new @app, @events
@log_writer = Puma::LogWriter.strings
@server = Puma::Server.new @app, @log_writer
end
def teardown

View File

@ -23,7 +23,7 @@ class WebServerTest < Minitest::Test
def setup
@tester = TestHandler.new
@server = Puma::Server.new @tester, Puma::Events.strings
@server = Puma::Server.new @tester, Puma::LogWriter.strings
@port = (@server.add_tcp_listener "127.0.0.1", 0).addr[1]
@tcp = "http://127.0.0.1:#{@port}"
@server.run