Skip to content

Commit

Permalink
Prevent loading with rack 3 (puma#3166)
Browse files Browse the repository at this point in the history
* Prevent booting with rack 3

* Move with_unbundled_env to integration helpers

* Version restriction test environment

* Allow skipping the wait period with the cli_server helper

* Test for the rack version restriction

* Fixup & Rename test file

* Minor puma.rb and rack/version_restriction.rb changes

---------

Co-authored-by: MSP-Greg <Greg.mpls@gmail.com>
  • Loading branch information
JoeDupuis and MSP-Greg committed Jun 10, 2023
1 parent f306d2e commit aec9425
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 13 deletions.
6 changes: 4 additions & 2 deletions lib/puma.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@

require 'thread'

# extension files should not be loaded with `require_relative`
require 'puma/puma_http11'
require 'puma/detect'
require 'puma/json_serialization'
require_relative 'puma/detect'
require_relative 'puma/json_serialization'
require_relative 'rack/version_restriction'

module Puma
autoload :Const, 'puma/const'
Expand Down
15 changes: 15 additions & 0 deletions lib/rack/version_restriction.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
begin
begin
# rack/version exists in Rack 2.2.0 and later, compatible with Ruby 2.3 and later
# we prefer to not load Rack
require 'rack/version'
rescue LoadError
require 'rack'
end

# Rack.release is needed for Rack v1, Rack::RELEASE was added in v2
if Gem::Version.new(Rack.release) >= Gem::Version.new("3.0.0")
raise StandardError.new "Puma 5 is not compatible with Rack 3, please upgrade to Puma 6 or higher."
end
rescue LoadError
end
4 changes: 4 additions & 0 deletions test/bundle_rack_3/Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
source "https://rubygems.org"

gem 'rack', '>= 3.0.0'
gem 'puma', path: '../..'
1 change: 1 addition & 0 deletions test/bundle_rack_3/config.ru
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
run lambda { |env| [200, {"Content-Type" => "text/plain"}, ["Hello World"]] }
13 changes: 11 additions & 2 deletions test/helpers/integration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,20 @@ def teardown

private

def with_unbundled_env
bundler_ver = Gem::Version.new(Bundler::VERSION)
if bundler_ver < Gem::Version.new('2.1.0')
Bundler.with_clean_env { yield }
else
Bundler.with_unbundled_env { yield }
end
end

def silent_and_checked_system_command(*args)
assert(system(*args, out: File::NULL, err: File::NULL))
end

def cli_server(argv, unix: false, config: nil, merge_err: false)
def cli_server(argv, unix: false, config: nil, merge_err: false, skip_waiting: false)
if config
config_file = Tempfile.new(%w(config .rb))
config_file.write config
Expand All @@ -77,7 +86,7 @@ def cli_server(argv, unix: false, config: nil, merge_err: false)
else
@server = IO.popen(cmd, "r")
end
wait_for_server_to_boot
wait_for_server_to_boot unless skip_waiting
@pid = @server.pid
@server
end
Expand Down
48 changes: 48 additions & 0 deletions test/test_rack_version_restriction.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
require_relative "helper"
require_relative "helpers/integration"

class TestRackVersionRestriction < TestIntegration
class PumaBooted < Timeout::Error; end

def setup
# Rack 3 minimum Ruby version is 2.4
skip if !::Puma::IS_MRI || RUBY_VERSION < '2.4'
super
end

def teardown
return if skipped?
FileUtils.rm_rf ["#{workdir}/vendor", "#{workdir}/Gemfile.lock"]
begin
# KILL works with all OS's
Process.kill(:KILL, @server.pid) if @server
rescue Errno::ESRCH
end
end

def test_prevent_booting_with_rack_3
msg = "Puma 5 is not compatible with Rack 3"
puma_crashed = false

Dir.chdir(workdir) do
with_unbundled_env do
silent_and_checked_system_command("bundle config --local path vendor/bundle")
silent_and_checked_system_command("bundle install")
Timeout.timeout(5, PumaBooted) do
cli_server './config.ru', merge_err: true, skip_waiting: true
sleep 0.1 until puma_crashed = @server.gets[msg]
end
end
end

rescue PumaBooted
ensure
assert puma_crashed, "Puma was expected to crash on boot, but it didn't! "
end

private

def workdir
File.expand_path("bundle_rack_3", __dir__)
end
end
9 changes: 0 additions & 9 deletions test/test_worker_gem_independence.rb
Original file line number Diff line number Diff line change
Expand Up @@ -133,13 +133,4 @@ def start_phased_restart

true while @server.gets !~ /booted in [.0-9]+s, phase: 1/
end

def with_unbundled_env
bundler_ver = Gem::Version.new(Bundler::VERSION)
if bundler_ver < Gem::Version.new('2.1.0')
Bundler.with_clean_env { yield }
else
Bundler.with_unbundled_env { yield }
end
end
end

0 comments on commit aec9425

Please sign in to comment.