diff --git a/Gemfile b/Gemfile index 48e9c9bf9f..3d96772254 100644 --- a/Gemfile +++ b/Gemfile @@ -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" diff --git a/lib/puma/rack_default.rb b/lib/puma/rack_default.rb index 0c17ee46cd..16c3b0762e 100644 --- a/lib/puma/rack_default.rb +++ b/lib/puma/rack_default.rb @@ -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 diff --git a/lib/rack/handler/puma.rb b/lib/rack/handler/puma.rb index 81ab022eb0..976dd24e08 100644 --- a/lib/rack/handler/puma.rb +++ b/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 diff --git a/test/test_rack_handler.rb b/test/test_rack_handler.rb index 11864d7249..c89cb8036a 100644 --- a/test/test_rack_handler.rb +++ b/test/test_rack_handler.rb @@ -1,17 +1,22 @@ require_relative "helper" -require "rack" - -if Rack::RELEASE < '3' +module TestRackUp + if ENV.key? "PUMA_CI_RACK_2" + require "rack" + RACK_HANDLER_MOD = ::Rack::Handler + else + require "rackup" + RACK_HANDLER_MOD = ::Rackup::Handler + end require "rack/handler/puma" class TestHandlerGetStrSym < Minitest::Test def test_handler - handler = Rack::Handler.get(:puma) - assert_equal Rack::Handler::Puma, handler - handler = Rack::Handler.get('Puma') - assert_equal Rack::Handler::Puma, handler + handler = RACK_HANDLER_MOD.get(:puma) + assert_equal RACK_HANDLER_MOD::Puma, handler + handler = RACK_HANDLER_MOD.get('Puma') + assert_equal RACK_HANDLER_MOD::Puma, handler end end @@ -30,7 +35,7 @@ def in_handler(app, options = {}) @launcher = nil thread = Thread.new do - Rack::Handler::Puma.run(app, **options) do |s, p| + RACK_HANDLER_MOD::Puma.run(app, **options) do |s, p| @launcher = s end end @@ -74,7 +79,7 @@ def test_port_wins_over_config File.open("config/puma.rb", "w") { |f| f << "port #{file_port}" } @options[:Port] = user_port - conf = Rack::Handler::Puma.config(->{}, @options) + conf = RACK_HANDLER_MOD::Puma.config(->{}, @options) conf.load assert_equal ["tcp://0.0.0.0:#{user_port}"], conf.options[:binds] @@ -95,7 +100,7 @@ def test_host_uses_supplied_port_default @options[:Host] = user_host @options[:Port] = user_port - conf = Rack::Handler::Puma.config(->{}, @options) + conf = RACK_HANDLER_MOD::Puma.config(->{}, @options) conf.load assert_equal ["tcp://#{user_host}:#{user_port}"], conf.options[:binds] @@ -103,7 +108,7 @@ def test_host_uses_supplied_port_default def test_ipv6_host_supplied_port_default @options[:Host] = "::1" - conf = Rack::Handler::Puma.config(->{}, @options) + conf = RACK_HANDLER_MOD::Puma.config(->{}, @options) conf.load assert_equal ["tcp://[::1]:9292"], conf.options[:binds] @@ -126,7 +131,7 @@ def test_config_file_wins_over_port File.open("config/puma.rb", "w") { |f| f << "port #{file_port}" } @options[:Port] = user_port - conf = Rack::Handler::Puma.config(->{}, @options) + conf = RACK_HANDLER_MOD::Puma.config(->{}, @options) conf.load assert_equal ["tcp://0.0.0.0:#{file_port}"], conf.options[:binds] @@ -145,7 +150,7 @@ def test_default_host_when_using_config_file @options[:Host] = "localhost" @options[:Port] = user_port - conf = Rack::Handler::Puma.config(->{}, @options) + conf = RACK_HANDLER_MOD::Puma.config(->{}, @options) conf.load assert_equal ["tcp://localhost:#{file_port}"], conf.options[:binds] @@ -164,7 +169,7 @@ def test_default_host_when_using_config_file_with_explicit_host @options[:Host] = "localhost" @options[:Port] = user_port - conf = Rack::Handler::Puma.config(->{}, @options) + conf = RACK_HANDLER_MOD::Puma.config(->{}, @options) conf.load assert_equal ["tcp://1.2.3.4:#{file_port}"], conf.options[:binds] @@ -179,7 +184,7 @@ def setup end def test_default_port_when_no_config_file - conf = Rack::Handler::Puma.config(->{}, @options) + conf = RACK_HANDLER_MOD::Puma.config(->{}, @options) conf.load assert_equal ["tcp://0.0.0.0:9292"], conf.options[:binds] @@ -193,7 +198,7 @@ def test_config_wins_over_default FileUtils.mkdir("config") File.open("config/puma.rb", "w") { |f| f << "port #{file_port}" } - conf = Rack::Handler::Puma.config(->{}, @options) + conf = RACK_HANDLER_MOD::Puma.config(->{}, @options) conf.load assert_equal ["tcp://0.0.0.0:#{file_port}"], conf.options[:binds] @@ -205,7 +210,7 @@ def test_user_port_wins_over_default_when_user_supplied_is_blank user_port = 5001 @options[:user_supplied_options] = [] @options[:Port] = user_port - conf = Rack::Handler::Puma.config(->{}, @options) + conf = RACK_HANDLER_MOD::Puma.config(->{}, @options) conf.load assert_equal ["tcp://0.0.0.0:#{user_port}"], conf.options[:binds] @@ -214,7 +219,7 @@ def test_user_port_wins_over_default_when_user_supplied_is_blank def test_user_port_wins_over_default user_port = 5001 @options[:Port] = user_port - conf = Rack::Handler::Puma.config(->{}, @options) + conf = RACK_HANDLER_MOD::Puma.config(->{}, @options) conf.load assert_equal ["tcp://0.0.0.0:#{user_port}"], conf.options[:binds] @@ -230,7 +235,7 @@ def test_user_port_wins_over_config File.open("config/puma.rb", "w") { |f| f << "port #{file_port}" } @options[:Port] = user_port - conf = Rack::Handler::Puma.config(->{}, @options) + conf = RACK_HANDLER_MOD::Puma.config(->{}, @options) conf.load assert_equal ["tcp://0.0.0.0:#{user_port}"], conf.options[:binds] @@ -239,7 +244,7 @@ def test_user_port_wins_over_config end def test_default_log_request_when_no_config_file - conf = Rack::Handler::Puma.config(->{}, @options) + conf = RACK_HANDLER_MOD::Puma.config(->{}, @options) conf.load assert_equal false, conf.options[:log_requests] @@ -252,7 +257,7 @@ def test_file_log_requests_wins_over_default_config 'test/config/t1_conf.rb' ] - conf = Rack::Handler::Puma.config(->{}, @options) + conf = RACK_HANDLER_MOD::Puma.config(->{}, @options) conf.load assert_equal file_log_requests_config, conf.options[:log_requests] @@ -266,10 +271,10 @@ def test_user_log_requests_wins_over_file_config 'test/config/t1_conf.rb' ] - conf = Rack::Handler::Puma.config(->{}, @options) + conf = RACK_HANDLER_MOD::Puma.config(->{}, @options) conf.load assert_equal user_log_requests_config, conf.options[:log_requests] end end -end # if Rack::RELEASE < '3' +end