【问题标题】:Sinatra Catching Exceptions for Custom Error PagesSinatra 捕获自定义错误页面的异常
【发布时间】:2015-07-05 01:10:55
【问题描述】:

我正在尝试处理模块化 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 &lt; DBC::Error
  • DBC::Error &lt; RuntimeError
  • 我理解为 Ruby RuntimeError &lt; Exception

但它error Exception 并没有像我想的那样捕获所有Exception

我做错了什么吗?还是一般不能捕获所有异常?

注意:除了提供的答案(两者都有效)之外,我还有set :raise_errors, true。您不需要在开发和生产中设置它。默认情况下,它设置为“测试”环境。

问题的本质是一些异常得到了处理,而另一些则没有。

【问题讨论】:

    标签: ruby exception exception-handling sinatra


    【解决方案1】:

    添加这个以防止 Sinatra 自己的错误页面干扰您的自定义错误处理程序:

    set :show_exceptions, false
    

    默认情况下,开发模式下设置为 true,生产模式下设置为 false。

    请注意,如果您遵循 Sinatra 自述文件中关于设置 set :show_exceptions, :after_handler 的建议,这将使您的错误处理程序即使在开发模式下也能运行(至少对于一些异常类),但是它还将为未捕获的异常启用生产中的内置错误页面。我不清楚它会尊重哪些错误处理程序,以及它将忽略哪些错误处理程序以支持内置调试页面。

    编辑:我意识到您还询问了错误处理程序的定义顺序。没关系; Sinatra 首先在应用程序类中查找与异常类的完全匹配,然后在其超类中查找。如果没有找到,它会重复搜索异常的超类等。因此,Exception 的处理程序只会被调用为没有更接近匹配的异常。

    【讨论】:

    • 有趣的发现。它在生产环境中根据需要捕获异常。但正如你所说,在开发模式下只捕获了一些错误。那是我有disable :show_exceptions
    【解决方案2】:

    这是来自Sinatra docs的相关信息:

    Sinatra 在开发环境下运行时会安装特殊的 not_found 和错误处理程序,以在您的浏览器中显示漂亮的堆栈跟踪和其他调试信息。

    这意味着,当您在开发中运行时,Sinatra 会创建一个默认的“catch-all”错误处理程序,其优先级高于您的 error Exception do .. end 块。

    一旦您进入生产模式(或通过disable :show_exceptions 在开发中禁用),您的error Exception do .. end 块应该会捕获您的所有异常。

    请注意,这些 error 块的定义顺序无关紧要。

    【讨论】:

      猜你喜欢
      • 2015-03-20
      • 1970-01-01
      • 1970-01-01
      • 2011-08-19
      • 1970-01-01
      • 1970-01-01
      • 2017-05-24
      • 2014-04-06
      • 1970-01-01
      相关资源
      最近更新 更多