diff options
author | Samuel Williams <samuel.williams@oriontransfer.co.nz> | 2020-03-11 12:41:25 +1300 |
---|---|---|
committer | Samuel Williams <samuel.williams@oriontransfer.co.nz> | 2020-07-28 18:19:12 +1200 |
commit | 918459ac2e0980198486e3091a0f9651d5a54413 (patch) | |
tree | 3b31412e1a3d8c732604dc88366c7932c3662a33 | |
parent | 649c72bab9e7b50d657b5b432d0c205c95c2be07 (diff) | |
download | rack-918459ac2e0980198486e3091a0f9651d5a54413.tar.gz |
Remove `rack.multithread`/`rack.multiprocess`/`rack.run_once`.
These variables generally come too late to be useful. Removed `Rack::Lock`
which depends on these variables.
-rw-r--r-- | CHANGELOG.md | 4 | ||||
-rw-r--r-- | README.rdoc | 1 | ||||
-rw-r--r-- | SPEC.rdoc | 13 | ||||
-rw-r--r-- | lib/rack.rb | 4 | ||||
-rw-r--r-- | lib/rack/handler/cgi.rb | 3 | ||||
-rw-r--r-- | lib/rack/handler/webrick.rb | 3 | ||||
-rwxr-xr-x | lib/rack/lint.rb | 19 | ||||
-rw-r--r-- | lib/rack/lock.rb | 32 | ||||
-rw-r--r-- | lib/rack/mock.rb | 3 | ||||
-rw-r--r-- | lib/rack/request.rb | 1 | ||||
-rw-r--r-- | test/spec_lock.rb | 203 | ||||
-rw-r--r-- | test/spec_session_pool.rb | 2 | ||||
-rw-r--r-- | test/spec_thin.rb | 3 | ||||
-rw-r--r-- | test/spec_webrick.rb | 3 |
14 files changed, 6 insertions, 288 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 1bc4a7ad..3766b6fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,10 @@ All notable changes to this project will be documented in this file. For info on - [[CVE-2020-8184](https://nvd.nist.gov/vuln/detail/CVE-2020-8184)] Do not allow percent-encoded cookie name to override existing cookie names. BREAKING CHANGE: Accessing cookie names that require URL encoding with decoded name no longer works. ([@fletchto99](https://github.com/fletchto99)) +### Removed + +- Remove `rack.multithread`/`rack.multiprocess`/`rack.run_once`. These variables generally come too late to be useful. Removed `Rack::Lock` which depends on these variables. ([#1618](https://github.com/rack/rack/pull/1591), [@ioquatix](https://github.com/ioquatix)) + ## [2.2.2] - 2020-02-11 ### Fixed diff --git a/README.rdoc b/README.rdoc index caebc845..37d9fa6a 100644 --- a/README.rdoc +++ b/README.rdoc @@ -77,7 +77,6 @@ middleware: * Rack::Files, for serving static files. * Rack::Head, for returning an empty body for HEAD requests. * Rack::Lint, for checking conformance to the \Rack API. -* Rack::Lock, for serializing requests using a mutex. * Rack::Logger, for setting a logger to handle logging errors. * Rack::MethodOverride, for modifying the request method based on a submitted parameter. @@ -74,19 +74,6 @@ Rack-specific variables: request URL. <tt>rack.input</tt>:: See below, the input stream. <tt>rack.errors</tt>:: See below, the error stream. -<tt>rack.multithread</tt>:: true if the application object may be - simultaneously invoked by another thread - in the same process, false otherwise. -<tt>rack.multiprocess</tt>:: true if an equivalent application object - may be simultaneously invoked by another - process, false otherwise. -<tt>rack.run_once</tt>:: true if the server expects - (but does not guarantee!) that the - application will only be invoked this one - time during the life of its containing - process. Normally, this will only be true - for a server based on CGI - (or something similar). <tt>rack.hijack?</tt>:: present and true if the server supports connection hijacking. See below, hijacking. <tt>rack.hijack</tt>:: an object responding to #call that must be diff --git a/lib/rack.rb b/lib/rack.rb index b931292e..31690bcc 100644 --- a/lib/rack.rb +++ b/lib/rack.rb @@ -55,9 +55,6 @@ module Rack RACK_SESSION = 'rack.session' RACK_SESSION_OPTIONS = 'rack.session.options' RACK_SHOWSTATUS_DETAIL = 'rack.showstatus.detail' - RACK_MULTITHREAD = 'rack.multithread' - RACK_MULTIPROCESS = 'rack.multiprocess' - RACK_RUNONCE = 'rack.run_once' RACK_URL_SCHEME = 'rack.url_scheme' RACK_HIJACK = 'rack.hijack' RACK_IS_HIJACK = 'rack.hijack?' @@ -94,7 +91,6 @@ module Rack autoload :Handler, "rack/handler" autoload :Head, "rack/head" autoload :Lint, "rack/lint" - autoload :Lock, "rack/lock" autoload :Logger, "rack/logger" autoload :MediaType, "rack/media_type" autoload :MethodOverride, "rack/method_override" diff --git a/lib/rack/handler/cgi.rb b/lib/rack/handler/cgi.rb index b514fe74..df0864a1 100644 --- a/lib/rack/handler/cgi.rb +++ b/lib/rack/handler/cgi.rb @@ -18,9 +18,6 @@ module Rack RACK_VERSION => Rack::VERSION, RACK_INPUT => Rack::RewindableInput.new($stdin), RACK_ERRORS => $stderr, - RACK_MULTITHREAD => false, - RACK_MULTIPROCESS => true, - RACK_RUNONCE => true, RACK_URL_SCHEME => ["yes", "on", "1"].include?(ENV[HTTPS]) ? "https" : "http" ) diff --git a/lib/rack/handler/webrick.rb b/lib/rack/handler/webrick.rb index 07c7f9e0..9ce73b40 100644 --- a/lib/rack/handler/webrick.rb +++ b/lib/rack/handler/webrick.rb @@ -75,9 +75,6 @@ module Rack RACK_VERSION => Rack::VERSION, RACK_INPUT => rack_input, RACK_ERRORS => $stderr, - RACK_MULTITHREAD => true, - RACK_MULTIPROCESS => false, - RACK_RUNONCE => false, RACK_URL_SCHEME => ["yes", "on", "1"].include?(env[HTTPS]) ? "https" : "http", RACK_IS_HIJACK => true, RACK_HIJACK => lambda { raise NotImplementedError, "only partial hijack is supported."}, diff --git a/lib/rack/lint.rb b/lib/rack/lint.rb index 67264771..c7c621ef 100755 --- a/lib/rack/lint.rb +++ b/lib/rack/lint.rb @@ -157,22 +157,6 @@ module Rack ## <tt>rack.errors</tt>:: See below, the error stream. - ## <tt>rack.multithread</tt>:: true if the application object may be - ## simultaneously invoked by another thread - ## in the same process, false otherwise. - - ## <tt>rack.multiprocess</tt>:: true if an equivalent application object - ## may be simultaneously invoked by another - ## process, false otherwise. - - ## <tt>rack.run_once</tt>:: true if the server expects - ## (but does not guarantee!) that the - ## application will only be invoked this one - ## time during the life of its containing - ## process. Normally, this will only be true - ## for a server based on CGI - ## (or something similar). - ## <tt>rack.hijack?</tt>:: present and true if the server supports ## connection hijacking. See below, hijacking. @@ -274,8 +258,7 @@ module Rack ## %w[REQUEST_METHOD SERVER_NAME QUERY_STRING - rack.version rack.input rack.errors - rack.multithread rack.multiprocess rack.run_once].each { |header| + rack.version rack.input rack.errors].each { |header| assert("env missing required key #{header}") { env.include? header } } diff --git a/lib/rack/lock.rb b/lib/rack/lock.rb deleted file mode 100644 index 4bae3a90..00000000 --- a/lib/rack/lock.rb +++ /dev/null @@ -1,32 +0,0 @@ -# frozen_string_literal: true - -require 'thread' - -module Rack - # Rack::Lock locks every request inside a mutex, so that every request - # will effectively be executed synchronously. - class Lock - def initialize(app, mutex = Mutex.new) - @app, @mutex = app, mutex - end - - def call(env) - @mutex.lock - @env = env - @old_rack_multithread = env[RACK_MULTITHREAD] - begin - response = @app.call(env.merge!(RACK_MULTITHREAD => false)) - returned = response << BodyProxy.new(response.pop) { unlock } - ensure - unlock unless returned - end - end - - private - - def unlock - @mutex.unlock - @env[RACK_MULTITHREAD] = @old_rack_multithread - end - end -end diff --git a/lib/rack/mock.rb b/lib/rack/mock.rb index f330ae18..c704ef82 100644 --- a/lib/rack/mock.rb +++ b/lib/rack/mock.rb @@ -44,9 +44,6 @@ module Rack RACK_VERSION => Rack::VERSION, RACK_INPUT => StringIO.new, RACK_ERRORS => StringIO.new, - RACK_MULTITHREAD => true, - RACK_MULTIPROCESS => true, - RACK_RUNONCE => false, }.freeze def initialize(app) diff --git a/lib/rack/request.rb b/lib/rack/request.rb index 74377ede..3225066f 100644 --- a/lib/rack/request.rb +++ b/lib/rack/request.rb @@ -159,7 +159,6 @@ module Rack def content_length; get_header('CONTENT_LENGTH') end def logger; get_header(RACK_LOGGER) end def user_agent; get_header('HTTP_USER_AGENT') end - def multithread?; get_header(RACK_MULTITHREAD) end # the referer of the client def referer; get_header('HTTP_REFERER') end diff --git a/test/spec_lock.rb b/test/spec_lock.rb deleted file mode 100644 index 89570498..00000000 --- a/test/spec_lock.rb +++ /dev/null @@ -1,203 +0,0 @@ -# frozen_string_literal: true - -require_relative 'helper' - -class Lock - attr_reader :synchronized - - def initialize - @synchronized = false - end - - def lock - @synchronized = true - end - - def unlock - @synchronized = false - end -end - -module LockHelpers - def lock_app(app, lock = Lock.new) - app = if lock - Rack::Lock.new app, lock - else - Rack::Lock.new app - end - Rack::Lint.new app - end -end - -describe Rack::Lock do - include LockHelpers - - describe 'Proxy' do - include LockHelpers - - it 'delegate each' do - env = Rack::MockRequest.env_for("/") - response = Class.new { - attr_accessor :close_called - def initialize; @close_called = false; end - def each; %w{ hi mom }.each { |x| yield x }; end - }.new - - app = lock_app(lambda { |inner_env| [200, { "Content-Type" => "text/plain" }, response] }) - response = app.call(env)[2] - list = [] - response.each { |x| list << x } - list.must_equal %w{ hi mom } - end - - it 'delegate to_path' do - lock = Lock.new - env = Rack::MockRequest.env_for("/") - - res = ['Hello World'] - def res.to_path ; "/tmp/hello.txt" ; end - - app = Rack::Lock.new(lambda { |inner_env| [200, { "Content-Type" => "text/plain" }, res] }, lock) - body = app.call(env)[2] - - body.must_respond_to :to_path - body.to_path.must_equal "/tmp/hello.txt" - end - - it 'not delegate to_path if body does not implement it' do - env = Rack::MockRequest.env_for("/") - - res = ['Hello World'] - - app = lock_app(lambda { |inner_env| [200, { "Content-Type" => "text/plain" }, res] }) - body = app.call(env)[2] - - body.wont_respond_to :to_path - end - end - - it 'call super on close' do - env = Rack::MockRequest.env_for("/") - response = Class.new { - attr_accessor :close_called - def initialize; @close_called = false; end - def close; @close_called = true; end - }.new - - app = lock_app(lambda { |inner_env| [200, { "Content-Type" => "text/plain" }, response] }) - app.call(env) - response.close_called.must_equal false - response.close - response.close_called.must_equal true - end - - it "not unlock until body is closed" do - lock = Lock.new - env = Rack::MockRequest.env_for("/") - response = Object.new - app = lock_app(lambda { |inner_env| [200, { "Content-Type" => "text/plain" }, response] }, lock) - lock.synchronized.must_equal false - response = app.call(env)[2] - lock.synchronized.must_equal true - response.close - lock.synchronized.must_equal false - end - - it "return value from app" do - env = Rack::MockRequest.env_for("/") - body = [200, { "Content-Type" => "text/plain" }, %w{ hi mom }] - app = lock_app(lambda { |inner_env| body }) - - res = app.call(env) - res[0].must_equal body[0] - res[1].must_equal body[1] - res[2].to_enum.to_a.must_equal ["hi", "mom"] - end - - it "call synchronize on lock" do - lock = Lock.new - env = Rack::MockRequest.env_for("/") - app = lock_app(lambda { |inner_env| [200, { "Content-Type" => "text/plain" }, %w{ a b c }] }, lock) - lock.synchronized.must_equal false - app.call(env) - lock.synchronized.must_equal true - end - - it "unlock if the app raises" do - lock = Lock.new - env = Rack::MockRequest.env_for("/") - app = lock_app(lambda { raise Exception }, lock) - lambda { app.call(env) }.must_raise Exception - lock.synchronized.must_equal false - end - - it "unlock if the app throws" do - lock = Lock.new - env = Rack::MockRequest.env_for("/") - app = lock_app(lambda {|_| throw :bacon }, lock) - lambda { app.call(env) }.must_throw :bacon - lock.synchronized.must_equal false - end - - it "set multithread flag to false" do - app = lock_app(lambda { |env| - env['rack.multithread'].must_equal false - [200, { "Content-Type" => "text/plain" }, %w{ a b c }] - }, false) - env = Rack::MockRequest.env_for("/") - env['rack.multithread'].must_equal true - _, _, body = app.call(env) - body.close - env['rack.multithread'].must_equal true - end - - it "reset original multithread flag when exiting lock" do - app = Class.new(Rack::Lock) { - def call(env) - env['rack.multithread'].must_equal true - super - end - }.new(lambda { |env| [200, { "Content-Type" => "text/plain" }, %w{ a b c }] }) - Rack::Lint.new(app).call(Rack::MockRequest.env_for("/")) - end - - it 'not unlock if an error is raised before the mutex is locked' do - lock = Class.new do - def initialize() @unlocked = false end - def unlocked?() @unlocked end - def lock() raise Exception end - def unlock() @unlocked = true end - end.new - env = Rack::MockRequest.env_for("/") - app = lock_app(proc { [200, { "Content-Type" => "text/plain" }, []] }, lock) - lambda { app.call(env) }.must_raise Exception - lock.unlocked?.must_equal false - end - - it "not reset the environment while the body is proxied" do - proxy = Class.new do - attr_reader :env - def initialize(env) @env = env end - end - app = Rack::Lock.new lambda { |env| [200, { "Content-Type" => "text/plain" }, proxy.new(env)] } - response = app.call(Rack::MockRequest.env_for("/"))[2] - response.env['rack.multithread'].must_equal false - end - - it "unlock if an exception occurs before returning" do - lock = Lock.new - env = Rack::MockRequest.env_for("/") - app = lock_app(proc { [].freeze }, lock) - lambda { app.call(env) }.must_raise Exception - lock.synchronized.must_equal false - end - - it "not replace the environment" do - env = Rack::MockRequest.env_for("/") - app = lock_app(lambda { |inner_env| [200, { "Content-Type" => "text/plain" }, [inner_env.object_id.to_s]] }) - - _, _, body = app.call(env) - - body.to_enum.to_a.must_equal [env.object_id.to_s] - end -end diff --git a/test/spec_session_pool.rb b/test/spec_session_pool.rb index aba93fb1..306786f6 100644 --- a/test/spec_session_pool.rb +++ b/test/spec_session_pool.rb @@ -225,7 +225,7 @@ describe Rack::Session::Pool do tnum = rand(7).to_i + 5 r = Array.new(tnum) do Thread.new(treq) do |run| - run.get('/', "HTTP_COOKIE" => cookie, 'rack.multithread' => true) + run.get('/', "HTTP_COOKIE" => cookie) end end.reverse.map{|t| t.run.join.value } r.each do |resp| diff --git a/test/spec_thin.rb b/test/spec_thin.rb index 5f714e0f..26917836 100644 --- a/test/spec_thin.rb +++ b/test/spec_thin.rb @@ -47,9 +47,6 @@ describe Rack::Handler::Thin do it "have rack headers" do GET("/") response["rack.version"].must_equal [1, 0] - response["rack.multithread"].must_equal false - response["rack.multiprocess"].must_equal false - response["rack.run_once"].must_equal false end it "have CGI headers on GET" do diff --git a/test/spec_webrick.rb b/test/spec_webrick.rb index b0bfa2b0..a6ea3cb5 100644 --- a/test/spec_webrick.rb +++ b/test/spec_webrick.rb @@ -50,9 +50,6 @@ describe Rack::Handler::WEBrick do it "have rack headers" do GET("/test") response["rack.version"].must_equal [1, 3] - response["rack.multithread"].must_equal true - assert_equal false, response["rack.multiprocess"] - assert_equal false, response["rack.run_once"] end it "have CGI headers on GET" do |