Freeze the middleware stack after it's built

So apps that accidentally add middlewares later aren't unwittingly dumping them in a black hole.

Closes #5911
This commit is contained in:
Jeremy Kemper 2012-04-20 12:17:03 -07:00
parent 99eae3f82a
commit 42f6e9fb38
3 changed files with 26 additions and 18 deletions

@ -110,7 +110,7 @@ def use(*args, &block)
def build(app = nil, &block)
app ||= block
raise "MiddlewareStack#build requires an app" unless app
middlewares.reverse.inject(app) { |a, e| e.build(a) }
middlewares.freeze.reverse.inject(app) { |a, e| e.build(a) }
end
protected

@ -17,31 +17,32 @@ def teardown
end
test "show exceptions middleware filter backtrace before logging" do
my_middleware = Struct.new(:app) do
def call(env)
raise "Failure"
controller :foo, <<-RUBY
class FooController < ActionController::Base
def index
raise 'oops'
end
end
end
RUBY
app.config.middleware.use my_middleware
get "/foo"
assert_equal 500, last_response.status
stringio = StringIO.new
Rails.logger = Logger.new(stringio)
get "/"
assert_no_match(/action_dispatch/, stringio.string)
log = File.read(Rails.application.config.paths["log"].first)
assert_no_match(/action_dispatch/, log, log)
assert_match(/oops/, log, log)
end
test "renders active record exceptions as 404" do
my_middleware = Struct.new(:app) do
def call(env)
raise ActiveRecord::RecordNotFound
controller :foo, <<-RUBY
class FooController < ActionController::Base
def index
raise ActiveRecord::RecordNotFound
end
end
end
RUBY
app.config.middleware.use my_middleware
get "/"
get "/foo"
assert_equal 404, last_response.status
end

@ -148,6 +148,13 @@ def app
assert_equal "Rack::Config", middleware.first
end
test "can't change middleware after it's built" do
boot!
assert_raise RuntimeError do
app.config.middleware.use Rack::Config
end
end
# ConditionalGet + Etag
test "conditional get + etag middlewares handle http caching based on body" do
make_basic_app