3

嗨,我刚刚有一个关于如何使用 ruby​​ rack 适当地管理异常处理的问题。

我目前正在使用 Sinatra/Rack 构建一个轻量级 API,并且每条路由都可能通过异常(例如缺少参数、无效格式等)。我希望能够捕获所有这些异常并在中间件应用程序中处理它们。我不想在每个 get、post、put、delete 块中捕获或“拯救”(例如 post '/me')

我尝试了类似的方法,其中 ExceptionHandler 位于机架堆栈的顶部。

我错过了什么?

class Api::ExceptionHandler

  def initialize(application)
    @application = application
  end

  def call(environment)
    @application.call environment
  rescue Api::MissingParameterError => parameter
    [ 400, { }, [ "parameter #{parameter} missing" ] ]
  end

end
4

2 回答 2

1

自 Sinatra 1.4 版本(Padrino 从 0.11 版本开始使用)以来,错误 http 状态定义发生了变化。这是sinatra-1.4.2/lib/sinatra/base.rb与“handle_exception”相关的一部分!功能


 if boom.respond_to? :http_status    status(boom.http_status)  elsif settings.use_code? and boom.respond_to? :code and boom.code.between? 400, 599      status(boom.code)  else    status(500)  end

因此,如果您的异常类具有“http_status”方法,则从中定义错误状态。由于这个原因,只有服务器错误(代码从 500 到 599 的错误)可以到达中间件,具体取决于“raise_errors”和“show_exceptions”设置(下面是相同的“handle_exception!”函数):


  return res if res or not server_error?
  raise boom if settings.raise_errors? or settings.show_exceptions?
好消息,默认错误状态为 500。因此,如果您确实需要异常来传播中间件,只需阻止您的异常类响应“http_status”方法或使用 500 到 599 以来的 http_status 代码。但对于问题中的示例,最好的方法是使用errorMax 描述的方法。

于 2013-06-08T10:45:29.677 回答
0

好的,正如 Catnapper 所说,上面的代码应该可以工作!我没有提到的是我所有的中间件都继承了一个继承 Sinatra::Base 的类。

并且 Sinatra 有自己的异常处理程序,可以这样修改

set :raise_errors, false
set :show_exceptions, false

这就是您在 sinatra 中编写异常处理程序的方式(对于问题中的示例):

error Api::MissingParameterError do |parameter|
  status 400
  headers { }
  body "parameter #{parameter} missing"
end
于 2013-02-11T18:04:54.243 回答