【问题标题】:Sinatra Error Handling in RubyRuby 中的 Sinatra 错误处理
【发布时间】:2014-08-14 02:37:13
【问题描述】:

我有一个简单的 Sinatra 休息,但我无法捕获错误。我也承认我对 Ruby 和 Sinatra 还很陌生。

当我在 post 端点提出错误时,我想报告传入的文档。我需要 1)处理发布结果中的错误(我可以访问 @incoming)或 2)将传入的文档传递给错误并在那里报告。

什么是更好的选择,选项 1 或选项 2?

  • 如果我继续使用选项 1,我如何防止错误出现错误(现在似乎正在这样做)
  • 如果我转到选项 2,如何将传入传递给错误?

下面是我的代码示例:

post ('/result') do 

  begin  
  @incoming = JSON.parse(request.body.read)

  //do something that causes an error
  rescue
     e = env['sinatra.error']
     url = request.url
     ip = request.ip

     @actlogpassblock = {  :message => e.message,
                        :path => url,
                        :ip => ip,
                        :timestamp => Time.new,
                        :type => "500",
                        :sub => "RES",
                        :payload => @incoming
                      }        
    action_log.insert(@actlogpassblock)
    status 500 
  end
end

error do
   status 500 
   e = env['sinatra.error']
   url = request.url
   ip = request.ip
   backtrace = "Application error\n#{e}\n#{e.backtrace.join("\n")}"

  @actlogpassblock = {  :message => e.message,
                        :path => url,
                        :ip => ip,
                        :timestamp => Time.new,
                        :type => "500",
                        :backtrace => backtrace
                      }        
  action_log.insert(@actlogpassblock)
  {:result => 'Ah Shucks! Something went wrong'}.to_json
end

【问题讨论】:

    标签: ruby error-handling sinatra


    【解决方案1】:

    如果我继续使用选项 1,我如何防止错误拾取 错误(就像现在一样)

    根据文档:

    每当从 路线阻塞...

    但是,这只适用于未捕获异常。试试这个:

    require 'sinatra'
    set :show_exceptions, false
    
    get '/' do
      begin
        raise ZeroDivisionError
      rescue ZeroDivisionError
        "rescue clause"
      end
    end
    
    error do
      "sinatra error handler" 
    end
    

    然后试试这个:

    get '/' do
      raise ZeroDivisionError
    end
    
    error do
      "sinatra error handler" 
    end
    

    此外,您可以定制错误处理程序以仅捕获某些异常,从而避免某些异常,例如

    error IndexError do ...
    

    或

    error MyCustomException do ...
    

    或

    error 400..510 do
    

    但对于包罗万象的版本:

    error do
    

    当路由块中发生未捕获的异常时,您无法阻止它执行...除非:

    错误处理程序只会被调用,但是,如果两个 Sinatra :raise_errors 和 :show_exceptions 配置选项已设置 假...

    :raise_errors 在“测试”环境中默认为 true,默认为 false 在其他环境。

    :show_exceptions 值在 “开发”环境并在其他环境中为 false

    辛特拉的作者说过:“这种[行为]是 故意的。这个想法是错误块将隐藏问题,你 通常不想在开发模式下这样做。

    https://github.com/sul-dlss/sdr-services-app/blob/master/Sinatra-error-handling.md

    如果我转到选项 2,如何将传入传递给错误?

    在路由块内创建的@variable 可以在错误块内看到。试试这个:

    require 'sinatra'
    set :show_exceptions, false
    
    get '/' do
      @incoming = "hello world"    #create @variable
      raise ZeroDivisionError
    end
    
    error ZeroDivisionError do
      @incoming                    #retrieve @variable
    end
    

    在浏览器中输入 url http://localhost:4567 后,您应该会在返回的网页上看到“hello world”。

    之所以有效是因为@variable 在创建@variable 时将其自身附加到任何对象自身;同样,当调用 @variable 时,它​​会从当时的任何对象中检索到 self 。当 Sinatra 执行路由块或错误块时,它会将 self 设置为同一个对象。

    选项 2 看起来不错,因为它将错误处理代码与应用程序代码分开。

    【讨论】:

    • 在我的情况下,错误块从未被调用,所以我在配置块中使用set :show_exceptions, false,现在所有的 RuntimeError 都被捕获了。
    • 我必须将 :raise_errors 设置为 true 才能让服务器处理它。似乎文档也同意这一点。 “启用 :raise_errors 设置会导致在应用程序之外引发异常,这些异常可能由服务器处理程序处理......”
    猜你喜欢
    • 2012-07-01
    • 2014-12-01
    • 2019-10-16
    • 1970-01-01
    • 1970-01-01
    • 2014-07-21
    • 1970-01-01
    • 1970-01-01
    • 2012-07-23
    相关资源
    最近更新 更多