Skip to content

Commit

Permalink
Fixup code for use with rackup gem (may be used with rack 3) (#3061)
Browse files Browse the repository at this point in the history
* Fixup code for use with rackup gem (may be used with rack 3)

* Update rack_default.rb

* Update puma.rb, use `include` instead of `module_eval`

* Changes per comments
  • Loading branch information
MSP-Greg committed Feb 12, 2023
1 parent 8c8c3ed commit 8092bf8
Show file tree
Hide file tree
Showing 4 changed files with 163 additions and 120 deletions.
1 change: 1 addition & 0 deletions Gemfile
Expand Up @@ -12,6 +12,7 @@ gem "minitest-proveit"
gem "minitest-stub-const"

gem "rack", (ENV['PUMA_CI_RACK_2'] ? "~> 2.2" : ">= 2.2")
gem "rackup" unless ENV['PUMA_CI_RACK_2']

gem "jruby-openssl", :platform => "jruby"

Expand Down
21 changes: 18 additions & 3 deletions lib/puma/rack_default.rb
Expand Up @@ -2,8 +2,23 @@

require_relative '../rack/handler/puma'

module Rack::Handler
def self.default(options = {})
Rack::Handler::Puma
# rackup was removed in Rack 3, it is now a separate gem
if Object.const_defined? :Rackup
module Rackup
module Handler
def self.default(options = {})
::Rackup::Handler::Puma
end
end
end
elsif Object.const_defined?(:Rack) && Rack::RELEASE < '3'
module Rack
module Handler
def self.default(options = {})
::Rack::Handler::Puma
end
end
end
else
raise "Rack 3 must be used with the Rackup gem"
end
210 changes: 116 additions & 94 deletions lib/rack/handler/puma.rb
@@ -1,114 +1,136 @@
# frozen_string_literal: true

require 'rack/handler'

module Rack
module Handler
module Puma
DEFAULT_OPTIONS = {
:Verbose => false,
:Silent => false
}

def self.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
# This module is used as an 'include' file in code at bottom of file
module 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

conf = ::Puma::Configuration.new(options, default_options) do |user_config, file_config, default_config|
if options.delete(:Verbose)
require 'rack/common_logger'
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
conf = ::Puma::Configuration.new(options, default_options) do |user_config, file_config, default_config|
if options.delete(:Verbose)
require 'rack/common_logger'
app = Rack::CommonLogger.new(app, STDOUT)
end
conf
end

def self.run(app, **options)
conf = self.config(app, options)
if options[:environment]
user_config.environment options[:environment]
end

log_writer = options.delete(:Silent) ? ::Puma::LogWriter.strings : ::Puma::LogWriter.stdio
if options[:Threads]
min, max = options.delete(:Threads).split(':', 2)
user_config.threads min, max
end

launcher = ::Puma::Launcher.new(conf, :log_writer => log_writer)
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

yield launcher if block_given?
begin
launcher.run
rescue Interrupt
puts "* Gracefully stopping, waiting for requests to finish"
launcher.stop
puts "* Goodbye!"
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)

def self.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)"
}
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 self.set_host_port_to_config(host, port, config)
config.clear_binds! if host || port

if host && (host[0,1] == '.' || host[0,1] == '/')
config.bind "unix://#{host}"
elsif host && host =~ /^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
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 && (host[0,1] == '.' || host[0,1] == '/')
config.bind "unix://#{host}"
elsif host && host =~ /^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

register :puma, Puma
# rackup was removed in Rack 3, it is now a separate gem
if Object.const_defined? :Rackup
module Rackup
module Handler
module Puma
class << self
include ::Puma::RackHandler
end
end
register :puma, Puma
end
end
elsif Object.const_defined?(:Rack) && Rack::RELEASE < '3'
module Rack
module Handler
module Puma
class << self
include ::Puma::RackHandler
end
end
register :puma, Puma
end
end
else
raise "You must install the rackup gem when using Rack 3"
end

0 comments on commit 8092bf8

Please sign in to comment.