【问题标题】:Handling third party API 400/500 responses in my RAILS controllers在我的 RAILS 控制器中处理第三方 API 400/500 响应
【发布时间】:2017-07-30 18:56:11
【问题描述】:

我正在学习如何在我的 rails 应用程序中实现第三方 API,但在处理错误响应时遇到了困难。

更具体地说,我正在尝试使用 gem fullcontact-api-ruby 来实现 Full Contact API。我已经使用我的 API 密钥整理了身份验证,并使用 gem 方法通过控制台发出了一些请求,没有问题。

我现在尝试在 Profiles Controller 中使用 API 包装器方法。这个想法是:

  1. 向控制器发送电子邮件作为参数
  2. 完整联系人 API 方法“person()”将检索与该电子邮件关联的信息
  3. 将创建一个配置文件对象,并使用 获取的 API 数据。
  4. 如果没有可用于该电子邮件的数据, 有一个错误的请求或服务器错误,然后是一个闪存错误和一个 会发生重定向。

我开始写这样的代码:

  # controllers/profiles_controller.rb
  def create
    @intel = FullContact.person(email: params[:email])
    if @intel[:status].to_s[0] != "2"
      flash[:error] = @intel[:status] 
      redirect_to profiles_path
    else
      # Code to create and populate a Profile instance
  end

由于成功响应的状态代码为 200,我假设我会从 Json 对象中提取代码并检查它是否以 2 开头,在这种情况下,我将继续创建实例。如果响应正常,这种方法就可以工作,因为我可以使用存储在@intel 中的 Json 对象。但是,当响应在 400s,500s 时,Rails 会触发一个异常,导致 Rails 崩溃,不允许我使用任何 JSON 对象:

FullContact::NotFound in ProfilesController#create
GET https://api.fullcontact.com/v2/person.json?apiKey=MY_API_KEY&email=THE_EMAIL_IM_USING_AS_PARAMETER: 404

我显然做错了什么。我尝试使用rescue StandardError => e 避免引发异常,但我想知道在我的控制器中处理此错误的正确方法是什么。有什么帮助吗?

---更新 1 尝试 STEVE 解决方案--

如果我在这样的请求之后挽救异常:

  def create
    @intel = FullContact.person(email: params[:email])
    rescue FullContact::NotFound

    if @intel.nil?
      flash[:error] = "Can't process request try again later"
      redirect_to profiles_path
    else
      # Code to create and populate a Profile instance
  end

@intel 设置为 nil(即未设置为响应 JSON 对象)。我想我只是更改条件以检查 @intel 是否为 nil 但由于某些奇怪的原因,当响应成功并且 @intel 设置为 JSON 对象时,第一个条件不会导致创建对象的方法。即使响应失败,也不确定如何将 @intel 设置为 JSON 响应。

【问题讨论】:

    标签: ruby-on-rails api fullcontact


    【解决方案1】:

    rescue 块的想法是定义当您从错误中拯救时发生的操作。

    构建方法的正确方法是......

    def create
      @intel = FullContact.person(email: params[:email])
      # Code to create and populate a Profile instance
    
    rescue FullContact::NotFound   
      flash[:error] = "Can't process request try again later"
      redirect_to profiles_path
    end 
    

    rescue之后出现的代码在救援时执行,否则忽略。

    格式是

    begin
      # normal code which may or may not encounter a raised error, if no
      #  raised error, it continues to normal completion
    rescue 
      # code that is only executed if there was a rescued error
    ensure
      # code that always happens, regardless of rescue or not, could be 
      # used to ensure necessary cleanup happens even if an exception raised
    end
    

    方法本身就是一个完整的begin 块,因此不需要上述格式大纲中的beginend

    您不需要ensure 块,只需添加它以表明存在该功能。也可以将elserescue 一起使用,但那是另一天了:)

    【讨论】:

    • 现在我明白了。我完全迷失了。这显然是我忽略的一个关键知识。非常感谢史蒂夫,非常感谢您的解释和指导。
    【解决方案2】:

    你可以的

    rescue FullContact::NotFound
    

    只是为了挽救那个错误。

    看起来该错误不会让您进行比较。即便如此,你的比较还是有缺陷的。由于您要将其转换为字符串,因此需要将其与字符串进行比较

    改变

       if @intel[:status].to_s[0] != 2
    

    进入

       if @intel[:status].to_s[0] != '2'
    

    【讨论】:

    • 谢谢史蒂夫。对学习如何捕获特定异常非常有帮助。这行得通。我想知道是否有任何方法可以知道像FullContact::NotFound 这样的 API 的潜在错误列表。您还认为这是处理 API 失败响应时的最佳做法吗?
    • 史蒂夫,实际上,在仔细检查了您的解决方案之后,它并没有像我想的那样工作,如果您有时间检查我上面的更新。
    • 您误解了rescue 的工作原理,请参阅我的其他答案。
    猜你喜欢
    • 2020-07-27
    • 2021-12-19
    • 2016-07-13
    • 1970-01-01
    • 2016-11-18
    • 2020-11-14
    • 1970-01-01
    • 1970-01-01
    • 2017-07-28
    相关资源
    最近更新 更多