From 012ac8f6b7dae4da423aef85d11cb9bd3d1b652f Mon Sep 17 00:00:00 2001 From: sdogruyol Date: Wed, 16 Nov 2016 20:27:01 +0300 Subject: [PATCH] Yield error in custom error handlers --- CHANGELOG.md | 7 +++++++ spec/common_exception_handler_spec.cr | 22 ++++++++++++++++++++++ src/kemal/common_exception_handler.cr | 14 +++++++------- src/kemal/config.cr | 6 +++--- src/kemal/dsl.cr | 2 +- 5 files changed, 40 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e1a4151..4097554 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,13 @@ end - Close response on `halt`. (thanks @samueleaton). - 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) diff --git a/spec/common_exception_handler_spec.cr b/spec/common_exception_handler_spec.cr index e531134..5442306 100644 --- a/spec/common_exception_handler_spec.cr +++ b/spec/common_exception_handler_spec.cr @@ -80,4 +80,26 @@ describe "Kemal::CommonExceptionHandler" do response.headers["Content-Type"].should eq "application/json" response.body.should eq "Something happened" 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 diff --git a/src/kemal/common_exception_handler.cr b/src/kemal/common_exception_handler.cr index bebde04..5a6756a 100644 --- a/src/kemal/common_exception_handler.cr +++ b/src/kemal/common_exception_handler.cr @@ -6,22 +6,22 @@ module Kemal def call(context) begin call_next(context) - rescue Kemal::Exceptions::RouteNotFound - call_exception_with_status_code(context, 404) - rescue Kemal::Exceptions::CustomException - call_exception_with_status_code(context, context.response.status_code) + rescue ex : Kemal::Exceptions::RouteNotFound + call_exception_with_status_code(context, ex, 404) + rescue ex : Kemal::Exceptions::CustomException + call_exception_with_status_code(context, ex, context.response.status_code) rescue ex : Exception 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 return render_500(context, ex.inspect_with_backtrace, verbosity) 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) 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 end end diff --git a/src/kemal/config.cr b/src/kemal/config.cr index 02bdc47..825298e 100644 --- a/src/kemal/config.cr +++ b/src/kemal/config.cr @@ -7,7 +7,7 @@ module Kemal class Config INSTANCE = Config.new 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) %} @ssl : Bool? {% else %} @@ -72,8 +72,8 @@ module Kemal ERROR_HANDLERS end - def add_error_handler(status_code, &handler : HTTP::Server::Context -> _) - ERROR_HANDLERS[status_code] = ->(context : HTTP::Server::Context) { handler.call(context).to_s } + def add_error_handler(status_code, &handler : HTTP::Server::Context, Exception -> _) + ERROR_HANDLERS[status_code] = ->(context : HTTP::Server::Context, error : Exception) { handler.call(context, error).to_s } end def extra_options(&@extra_options : OptionParser ->) diff --git a/src/kemal/dsl.cr b/src/kemal/dsl.cr index 2512881..1c8249a 100644 --- a/src/kemal/dsl.cr +++ b/src/kemal/dsl.cr @@ -15,6 +15,6 @@ def ws(path, &block : HTTP::WebSocket, HTTP::Server::Context -> Void) Kemal::WebSocketHandler.new path, &block 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 end