1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
|
# frozen_string_literal: true
module Puma
# This module is used as an 'include' file in code at bottom of file. It loads
# into either `Rackup::Handler::Puma` or `Rack::Handler::Puma`.
module RackHandler
DEFAULT_OPTIONS = {
:Verbose => false,
:Silent => false
}
def config(app, options = {})
require_relative '../../puma'
require_relative '../../puma/configuration'
require_relative '../../puma/log_writer'
require_relative '../../puma/launcher'
default_options = DEFAULT_OPTIONS.dup
# Libraries pass in values such as :Port and there is no way to determine
# if it is a default provided by the library or a special value provided
# by the user. A special key `user_supplied_options` can be passed. This
# contains an array of all explicitly defined user options. We then
# know that all other values are defaults
if user_supplied_options = options.delete(:user_supplied_options)
(options.keys - user_supplied_options).each do |k|
default_options[k] = options.delete(k)
end
end
@events = options[:events] || ::Puma::Events.new
conf = ::Puma::Configuration.new(options, default_options.merge({events: @events})) do |user_config, file_config, default_config|
if options.delete(:Verbose)
begin
require 'rack/commonlogger' # Rack 1.x
rescue LoadError
require 'rack/common_logger' # Rack 2 and later
end
app = ::Rack::CommonLogger.new(app, STDOUT)
end
if options[:environment]
user_config.environment options[:environment]
end
if options[:Threads]
min, max = options.delete(:Threads).split(':', 2)
user_config.threads min, max
end
if options[:Host] || options[:Port]
host = options[:Host] || default_options[:Host]
port = options[:Port] || default_options[:Port]
self.set_host_port_to_config(host, port, user_config)
end
if default_options[:Host]
file_config.set_default_host(default_options[:Host])
end
self.set_host_port_to_config(default_options[:Host], default_options[:Port], default_config)
user_config.app app
end
conf
end
def run(app, **options)
conf = self.config(app, options)
log_writer = options.delete(:Silent) ? ::Puma::LogWriter.strings : ::Puma::LogWriter.stdio
launcher = ::Puma::Launcher.new(conf, :log_writer => log_writer, events: @events)
yield launcher if block_given?
begin
launcher.run
rescue Interrupt
puts "* Gracefully stopping, waiting for requests to finish"
launcher.stop
puts "* Goodbye!"
end
end
def valid_options
{
"Host=HOST" => "Hostname to listen on (default: localhost)",
"Port=PORT" => "Port to listen on (default: 8080)",
"Threads=MIN:MAX" => "min:max threads to use (default 0:16)",
"Verbose" => "Don't report each request (default: false)"
}
end
def set_host_port_to_config(host, port, config)
config.clear_binds! if host || port
if host&.start_with? '.', '/', '@'
config.bind "unix://#{host}"
elsif host&.start_with? 'ssl://'
uri = URI.parse(host)
uri.port ||= port || ::Puma::Configuration::DEFAULTS[:tcp_port]
config.bind uri.to_s
else
if host
port ||= ::Puma::Configuration::DEFAULTS[:tcp_port]
end
if port
host ||= ::Puma::Configuration::DEFAULTS[:tcp_host]
config.port port, host
end
end
end
end
end
# rackup was removed in Rack 3, it is now a separate gem
if Object.const_defined?(:Rackup) && ::Rackup.const_defined?(:Handler)
module Rackup
module Handler
module Puma
class << self
include ::Puma::RackHandler
end
end
register :puma, Puma
end
end
else
do_register = Object.const_defined?(:Rack) && ::Rack.release < '3'
module Rack
module Handler
module Puma
class << self
include ::Puma::RackHandler
end
end
end
end
::Rack::Handler.register(:puma, ::Rack::Handler::Puma) if do_register
end
|