# A handler that invokes the next handler and, if that next handler raises
# an exception, returns with a 500 (Internal Server Error) status code.
#
# In verbose mode prints the exception with its backtrace to the response.
# Otherwise a generic error message is returned to the client.
#
# This handler also logs the exceptions to the specified logger or
# the logger for the source "http.server" by default.
#
# NOTE: To use `ErrorHandler`, you must explicitly import it with `require "http"`
class HTTP::ErrorHandler
  include HTTP::Handler

  def initialize(@verbose : Bool = false, @log = Log.for("http.server"))
  end

  def call(context : HTTP::Server::Context) : Nil
    call_next(context)
  rescue ex : HTTP::Server::ClientError
    @log.debug(exception: ex.cause) { ex.message }
  rescue ex : Exception
    @log.error(exception: ex) { "Unhandled exception" }
    unless context.response.closed? || context.response.wrote_headers?
      if @verbose
        context.response.reset
        context.response.status = :internal_server_error
        context.response.content_type = "text/plain"
        context.response.print("ERROR: ")
        context.response.puts(ex.inspect_with_backtrace)
      else
        context.response.respond_with_status(:internal_server_error)
      end
    end
  end
end
