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:

: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