在sinatra中调用halt不会设置sinatra.error



我的用例是我想在sinatra中进行错误处理。为此,我正在设置错误处理程序如下

error 0..600 do
  @@logger.error("error reason #{env['sinatra.error']}")
end

如果错误是由显式引发异常引起的,则sinatra.error变量设置为正确

get '/' do
  raise "Fail the request"
end 

但是,如果使用halt来终止请求,则不会设置sinatra.error。查看sinatra代码,这似乎与预期的一样,因为抛出:stop会导致控制流一直向上调用,从而绕过sinatra.error变量的设置。

我的问题是如何在暂停的同时使用错误处理程序,以便在错误处理程序中了解错误的原因。

我认为您看到的行为源于halt的预期目的。当你调用它时,你不一定是在错误地发出信号;您只希望执行立即停止,这在过滤器中特别有用。如果你查看Sinatra的自述,它会说你使用halt"立即停止过滤器或路由使用中的请求"。当然,你通常会因为一个错误而这么做。

值得注意的是,您定义的错误处理程序不仅在发生错误时被调用,而且在提供常规请求时也被调用,包括状态为200的请求。在这些情况下,也不会设置env[sinatra.error]

您可以在错误处理程序中检查异常,如果不可用,则检查响应代码。例如(注意这是一个经典的应用程序):

error 0..600 do
  boom = @env['sinatra.error']
  status = response.status
  case
  when boom != nil
    puts 'exception: ' + boom
  when status != 200
    puts 'error: ' + status
  end
end

一个结果是,在这个处理程序中,正常请求与被halt中断的请求无法区分,因为两者都会生成200状态代码。但是,如果使用halt报告错误,那么无论如何都应该使用类似500的错误代码。

最新更新