class Rack::ShowExceptions
def accepts_html?(env)
def accepts_html?(env) Rack::Utils.best_q_match(env["HTTP_ACCEPT"], %w[text/html]) end
def call(env)
def call(env) @app.call(env) rescue StandardError, LoadError, SyntaxError => e exception_string = dump_exception(e) env[RACK_ERRORS].puts(exception_string) env[RACK_ERRORS].flush if accepts_html?(env) content_type = "text/html" body = pretty(env, e) else content_type = "text/plain" body = exception_string end [ 500, { CONTENT_TYPE => content_type, CONTENT_LENGTH => body.bytesize.to_s, }, [body], ] end
def dump_exception(exception)
def dump_exception(exception) if exception.respond_to?(:detailed_message) message = exception.detailed_message(highlight: false) else message = exception.message end string = "#{exception.class}: #{message}\n".dup string << exception.backtrace.map { |l| "\t#{l}" }.join("\n") string end
def h(obj) # :nodoc:
def h(obj) # :nodoc: case obj when String Utils.escape_html(obj) else Utils.escape_html(obj.inspect) end end
def initialize(app)
def initialize(app) @app = app end
def prefers_plaintext?(env)
def prefers_plaintext?(env) !accepts_html?(env) end
def pretty(env, exception)
def pretty(env, exception) req = Rack::Request.new(env) # This double assignment is to prevent an "unused variable" warning. # Yes, it is dumb, but I don't like Ruby yelling at me. path = path = (req.script_name + req.path_info).squeeze("/") # This double assignment is to prevent an "unused variable" warning. # Yes, it is dumb, but I don't like Ruby yelling at me. frames = frames = exception.backtrace.map { |line| frame = OpenStruct.new if line =~ /(.*?):(\d+)(:in `(.*)')?/ frame.filename = $1 frame.lineno = $2.to_i frame.function = $4 begin lineno = frame.lineno - 1 lines = ::File.readlines(frame.filename) frame.pre_context_lineno = [lineno - CONTEXT, 0].max frame.pre_context = lines[frame.pre_context_lineno...lineno] frame.context_line = lines[lineno].chomp frame.post_context_lineno = [lineno + CONTEXT, lines.size].min frame.post_context = lines[lineno + 1..frame.post_context_lineno] rescue end frame else nil end }.compact template.result(binding) end
def template
def template TEMPLATE end