Sinatra 捕获自定义错误页面的异常
Sinatra Catching Exceptions for Custom Error Pages
我正在尝试处理模块化 Sinatra 应用程序中的错误。我们在整个应用程序中引发了各种错误,我写了一些类似的东西来捕获错误,认为它会分层发生。
我用来处理错误的文件如下所示。
#!/usr/bin/env ruby
# @class class RApp
# @brief Sinatra main routes overloading for App class
class RApp < Sinatra::Base
# @fn not_found do {{{
# @brief Not found error page
not_found do
render_error 404, _('Not Found'), env['sinatra.error'].message
end # }}}
# @fn error ServiceNotAvailableError do {{{
# @brief Handle ServiceNotFoundException, commonly associated with communication
# errors with external required services like Ambrosia, Saba
error ServiceNotAvailableError do
render_error 503, _('Service Not Available'), env['sinatra.error'].message
end # }}}
# @fn error Exception do {{{
# @brief Handle general internal errors
error Exception do
render_error 500, _('Internal Server Error'), env['sinatra.error'].message
end # }}}
error DBC::InvalidUUIDError do
"Invalid UUID Error"
end
# @fn def show_error code, title, message, view = nil {{{
# @brief Displays the proper message (html or text) based on if the request is XHR or otherwise
def render_error code, title, message, view = nil
view = code.to_s if view.nil?
if request.xhr?
halt code, message
else
halt code, slim(:"error_pages/#{view}", locals: {title: title, message: message})
end
end # }}}
# Just for testing
get '/errors/:type' do |type|
raise Object.const_get(type)
end
end # of class RApp < Sinatra::Base }}}
# vim:ts=2:tw=100:wm=100
我以为它会按照文件中的顺序进行尝试,这似乎是真的。
问题是什么 Exception
并没有捕捉到所有异常。
例如我有 DBC::InvalidUUIDError
就是这样
DBC::InvalidUUIDErrror < DBC::Error
DBC::Error < RuntimeError
- 我的理解是 Ruby
RuntimeError < Exception
但它 error Exception
并没有像我想的那样捕获所有 Exception
。
我是不是做错了什么?还是一般无法捕获所有异常?
注意:除了提供的答案(两者都有效)之外,我还有 set :raise_errors, true
。您不需要在开发和生产中设置它。默认设置为 'test' env.
事情的性质是处理了一些例外情况,有些则没有。
添加这个以防止 Sinatra 自己的错误页面干扰您的自定义错误处理程序:
set :show_exceptions, false
默认情况下,该设置在开发模式下为 true,在生产模式下为 false。
请注意,如果您遵循 Sinatra 自述文件关于设置 set :show_exceptions, :after_handler
的建议,这将使您的错误处理程序即使在开发模式下也能达到 运行(至少对于 some exception classes), 但它也会为未捕获的异常启用生产中的内置错误页面。我不清楚它会尊重哪些错误处理程序,以及它会忽略哪些错误处理程序以支持内置调试页面。
编辑: 我意识到您还询问了错误处理程序的定义顺序。没关系; Sinatra 首先在应用 class 中查找与异常 class 完全匹配的内容,然后在它的超级 class 中查找。如果没有找到,它会重复搜索异常的 superclass,等等。因此,Exception 的处理程序只会在没有更接近匹配的异常时被调用。
这是来自 Sinatra docs 的相关信息:
Sinatra installs special not_found and error handlers when running under the development environment to display nice stack traces and additional debugging information in your browser.
这意味着,当您 运行 处于开发阶段时,Sinatra 会创建一个默认的 "catch-all" 错误处理程序,该处理程序的优先级高于您的 error Exception do .. end
块。
一旦您进入生产模式(或通过 disable :show_exceptions
在开发中禁用),您的 error Exception do .. end
块应该捕获所有异常。
请注意,这些 error
块的定义顺序无关紧要。
我正在尝试处理模块化 Sinatra 应用程序中的错误。我们在整个应用程序中引发了各种错误,我写了一些类似的东西来捕获错误,认为它会分层发生。
我用来处理错误的文件如下所示。
#!/usr/bin/env ruby
# @class class RApp
# @brief Sinatra main routes overloading for App class
class RApp < Sinatra::Base
# @fn not_found do {{{
# @brief Not found error page
not_found do
render_error 404, _('Not Found'), env['sinatra.error'].message
end # }}}
# @fn error ServiceNotAvailableError do {{{
# @brief Handle ServiceNotFoundException, commonly associated with communication
# errors with external required services like Ambrosia, Saba
error ServiceNotAvailableError do
render_error 503, _('Service Not Available'), env['sinatra.error'].message
end # }}}
# @fn error Exception do {{{
# @brief Handle general internal errors
error Exception do
render_error 500, _('Internal Server Error'), env['sinatra.error'].message
end # }}}
error DBC::InvalidUUIDError do
"Invalid UUID Error"
end
# @fn def show_error code, title, message, view = nil {{{
# @brief Displays the proper message (html or text) based on if the request is XHR or otherwise
def render_error code, title, message, view = nil
view = code.to_s if view.nil?
if request.xhr?
halt code, message
else
halt code, slim(:"error_pages/#{view}", locals: {title: title, message: message})
end
end # }}}
# Just for testing
get '/errors/:type' do |type|
raise Object.const_get(type)
end
end # of class RApp < Sinatra::Base }}}
# vim:ts=2:tw=100:wm=100
我以为它会按照文件中的顺序进行尝试,这似乎是真的。
问题是什么 Exception
并没有捕捉到所有异常。
例如我有 DBC::InvalidUUIDError
就是这样
DBC::InvalidUUIDErrror < DBC::Error
DBC::Error < RuntimeError
- 我的理解是 Ruby
RuntimeError < Exception
但它 error Exception
并没有像我想的那样捕获所有 Exception
。
我是不是做错了什么?还是一般无法捕获所有异常?
注意:除了提供的答案(两者都有效)之外,我还有 set :raise_errors, true
。您不需要在开发和生产中设置它。默认设置为 'test' env.
事情的性质是处理了一些例外情况,有些则没有。
添加这个以防止 Sinatra 自己的错误页面干扰您的自定义错误处理程序:
set :show_exceptions, false
默认情况下,该设置在开发模式下为 true,在生产模式下为 false。
请注意,如果您遵循 Sinatra 自述文件关于设置 set :show_exceptions, :after_handler
的建议,这将使您的错误处理程序即使在开发模式下也能达到 运行(至少对于 some exception classes), 但它也会为未捕获的异常启用生产中的内置错误页面。我不清楚它会尊重哪些错误处理程序,以及它会忽略哪些错误处理程序以支持内置调试页面。
编辑: 我意识到您还询问了错误处理程序的定义顺序。没关系; Sinatra 首先在应用 class 中查找与异常 class 完全匹配的内容,然后在它的超级 class 中查找。如果没有找到,它会重复搜索异常的 superclass,等等。因此,Exception 的处理程序只会在没有更接近匹配的异常时被调用。
这是来自 Sinatra docs 的相关信息:
Sinatra installs special not_found and error handlers when running under the development environment to display nice stack traces and additional debugging information in your browser.
这意味着,当您 运行 处于开发阶段时,Sinatra 会创建一个默认的 "catch-all" 错误处理程序,该处理程序的优先级高于您的 error Exception do .. end
块。
一旦您进入生产模式(或通过 disable :show_exceptions
在开发中禁用),您的 error Exception do .. end
块应该捕获所有异常。
请注意,这些 error
块的定义顺序无关紧要。