Yield error in custom error handlers

This commit is contained in:
sdogruyol 2016-11-16 20:27:01 +03:00
parent 14b094d52f
commit 012ac8f6b7
5 changed files with 40 additions and 11 deletions

View file

@ -44,6 +44,13 @@ end
- Close response on `halt`. (thanks @samueleaton). - Close response on `halt`. (thanks @samueleaton).
- Update `Radix` to `v0.3.4`. - Update `Radix` to `v0.3.4`.
- `error` handler now also yields error. For example you can get the error mesasage like
```crystal
error 500 do |env, err|
err.message
end
```
# 0.16.1 (12-10-2016) # 0.16.1 (12-10-2016)

View file

@ -80,4 +80,26 @@ describe "Kemal::CommonExceptionHandler" do
response.headers["Content-Type"].should eq "application/json" response.headers["Content-Type"].should eq "application/json"
response.body.should eq "Something happened" response.body.should eq "Something happened"
end end
it "renders custom error with env and error" do
error 500 do |env, err|
err.message
end
get "/" do |env|
env.response.content_type = "application/json"
env.response.status_code = 500
end
request = HTTP::Request.new("GET", "/")
io = MemoryIO.new
response = HTTP::Server::Response.new(io)
context = HTTP::Server::Context.new(request, response)
Kemal::CommonExceptionHandler::INSTANCE.next = Kemal::RouteHandler::INSTANCE
Kemal::CommonExceptionHandler::INSTANCE.call(context)
response.close
io.rewind
response = HTTP::Client::Response.from_io(io, decompress: false)
response.status_code.should eq 500
response.headers["Content-Type"].should eq "application/json"
response.body.should eq "Rendered error with 500"
end
end end

View file

@ -6,22 +6,22 @@ module Kemal
def call(context) def call(context)
begin begin
call_next(context) call_next(context)
rescue Kemal::Exceptions::RouteNotFound rescue ex : Kemal::Exceptions::RouteNotFound
call_exception_with_status_code(context, 404) call_exception_with_status_code(context, ex, 404)
rescue Kemal::Exceptions::CustomException rescue ex : Kemal::Exceptions::CustomException
call_exception_with_status_code(context, context.response.status_code) call_exception_with_status_code(context, ex, context.response.status_code)
rescue ex : Exception rescue ex : Exception
Kemal.config.logger.write("Exception: #{ex.inspect_with_backtrace}\n") Kemal.config.logger.write("Exception: #{ex.inspect_with_backtrace}\n")
return call_exception_with_status_code(context, 500) if Kemal.config.error_handlers.has_key?(500) return call_exception_with_status_code(context, ex, 500) if Kemal.config.error_handlers.has_key?(500)
verbosity = Kemal.config.env == "production" ? false : true verbosity = Kemal.config.env == "production" ? false : true
return render_500(context, ex.inspect_with_backtrace, verbosity) return render_500(context, ex.inspect_with_backtrace, verbosity)
end end
end end
def call_exception_with_status_code(context, status_code) def call_exception_with_status_code(context, exception, status_code)
if Kemal.config.error_handlers.has_key?(status_code) if Kemal.config.error_handlers.has_key?(status_code)
context.response.content_type = "text/html" unless context.response.headers.has_key?("Content-Type") context.response.content_type = "text/html" unless context.response.headers.has_key?("Content-Type")
context.response.print Kemal.config.error_handlers[status_code].call(context) context.response.print Kemal.config.error_handlers[status_code].call(context, exception)
context context
end end
end end

View file

@ -7,7 +7,7 @@ module Kemal
class Config class Config
INSTANCE = Config.new INSTANCE = Config.new
HANDLERS = [] of HTTP::Handler HANDLERS = [] of HTTP::Handler
ERROR_HANDLERS = {} of Int32 => HTTP::Server::Context -> String ERROR_HANDLERS = {} of Int32 => HTTP::Server::Context, Exception -> String
{% if flag?(:without_openssl) %} {% if flag?(:without_openssl) %}
@ssl : Bool? @ssl : Bool?
{% else %} {% else %}
@ -72,8 +72,8 @@ module Kemal
ERROR_HANDLERS ERROR_HANDLERS
end end
def add_error_handler(status_code, &handler : HTTP::Server::Context -> _) def add_error_handler(status_code, &handler : HTTP::Server::Context, Exception -> _)
ERROR_HANDLERS[status_code] = ->(context : HTTP::Server::Context) { handler.call(context).to_s } ERROR_HANDLERS[status_code] = ->(context : HTTP::Server::Context, error : Exception) { handler.call(context, error).to_s }
end end
def extra_options(&@extra_options : OptionParser ->) def extra_options(&@extra_options : OptionParser ->)

View file

@ -15,6 +15,6 @@ def ws(path, &block : HTTP::WebSocket, HTTP::Server::Context -> Void)
Kemal::WebSocketHandler.new path, &block Kemal::WebSocketHandler.new path, &block
end end
def error(status_code, &block : HTTP::Server::Context -> _) def error(status_code, &block : HTTP::Server::Context, Exception -> _)
Kemal.config.add_error_handler status_code, &block Kemal.config.add_error_handler status_code, &block
end end