Reduce implementation of Sinatra::ShowExceptions to match Rack behavior

Closes #721

Although this is a behavior change, it's one that removes confusion about the
difference between Sinatra and Rack exception handling.

As well, this change removes duplication between the two APIs and reduces
chance of bugs from upstream changes.
This commit is contained in:
Zachary Scott 2016-05-10 17:08:15 +09:00
parent 57c2ebb854
commit 36e5b26d35
2 changed files with 5 additions and 39 deletions

View File

@ -10,50 +10,12 @@ module Sinatra
# Be careful when you use this on public-facing sites as it could reveal
# information helpful to attackers.
class ShowExceptions < Rack::ShowExceptions
@@eats_errors = Object.new
def @@eats_errors.flush(*) end
def @@eats_errors.puts(*) end
def initialize(app)
@app = app
end
def call(env)
@app.call(env)
rescue Exception => e
errors, env["rack.errors"] = env["rack.errors"], @@eats_errors
if prefers_plain_text?(env)
content_type = "text/plain"
exception = dump_exception(e)
else
content_type = "text/html"
exception = pretty(env, e)
end
env["rack.errors"] = errors
# Post 893a2c50 in rack/rack, the #pretty method above, implemented in
# Rack::ShowExceptions, returns a String instead of an array.
body = Array(exception)
[
500,
{
"Content-Type" => content_type,
"Content-Length" => body.join.bytesize.to_s
},
body
]
@app = app
end
private
def prefers_plain_text?(env)
!(Request.new(env).preferred_type("text/plain","text/html") == "text/html") &&
[/curl/].index{|item| item =~ env["HTTP_USER_AGENT"]}
end
def frame_class(frame)
if frame.filename =~ /lib\/sinatra.*\.rb/
"framework"

View File

@ -235,6 +235,10 @@ class SettingsTest < Minitest::Test
klass = Sinatra.new(Sinatra::Application)
mock_app(klass) {
enable :show_exceptions
# Because this test is run under `RACK_ENV=test`, unless we change the
# environment or set `preferred_type` then this test will fail and
# `ShowExceptions` will print the exception to stdout.
set :preferred_type, 'text/html'
get '/' do
raise StandardError