【问题标题】:rails 5 api app with json error response instead of html error response带有json错误响应而不是html错误响应的rails 5 api应用程序
【发布时间】:2018-12-17 17:30:30
【问题描述】:

如果我使用 --api 标志在 Rails 中创建应用程序,我的错误响应是 html 而不是 json。

如何更改默认错误处理程序,以便每当控制器操作中引发错误时,我都会收到仅包含错误和 http 状态的 json 响应?

现在我在每个自定义操作中都使用下面的代码

rescue => e
    response.status = 422
    render json: { error: e.message }

我宁愿不必每次都添加这个......

更新: 我在应用控制器中使用了rescue_from方法

rescue_from Exception do |exception|
    render json: exception, status: 500
end

但是我觉得这样很不对劲,status会一直硬编码为500

【问题讨论】:

  • 你可以在你的application_controller中添加rescue_from来捕捉每一个错误apidock.com/rails/ActiveSupport/Rescuable/ClassMethods/…
  • 如果我这样做了,我将不会拥有我通常会收到的状态......这怎么不是已经内置了??
  • 嗯,我没有完全得到你真正想要的东西。但是如果你想渲染不同的消息和状态取决于异常,那么你可以设置多个rescue_from。或者您可以定义多个 error_render 方法并将其排序到一个大的 rescue_from 中。 PS:也请不要抢救Exception。将其更改为 StandardError。
  • 我在我的路由中添加了默认值:{ format: :json } 并对其进行了转换 - 但是我仍然在更改所有路由的默认格式,因此对配置的任何建议将不胜感激:)

标签: ruby-on-rails json ruby http


【解决方案1】:

您可以在路由中添加格式为 json,这样它总是会接受如下 json 格式的请求

namespace :api, as: nil, defaults: { format: :json } do
     devise_for :users, controllers: {
        registrations: "api/v1/users/registrations",
        passwords: "api/v1/users/passwords"
      }

      resources :products, only: [:show,:index] do
        get "check_product_avaibility"
        get "filter", on: :collection
      end
end

为了全局处理错误,您可以在应用程序控制器文件中添加 around_action

around_action :handle_exceptions, if: proc { request.path.include?('/api') }

# Catch exception and return JSON-formatted error
  def handle_exceptions
    begin
      yield
    rescue ActiveRecord::RecordNotFound => e
      @status = 404
      @message = 'Record not found'
    rescue ActiveRecord::RecordInvalid => e
      render_unprocessable_entity_response(e.record) && return
    rescue ArgumentError => e
      @status = 400
    rescue StandardError => e
      @status = 500
    end
    json_response({ success: false, message: @message || e.class.to_s, errors: [{ detail: e.message }] }, @status) unless e.class == NilClass
  end

注意:render_unprocessable_entity_response 和 json_response 是自定义方法,您可以添加自己的方法来渲染 json 响应。

【讨论】:

  • 但是既然引入了 --api 标志,他们肯定会改变对 json 的默认响应吗?不是有一个可以更改的简单配置吗?我很惊讶它没有内置...您上面的代码正在将代码添加到我认为会添加到 rails 框架的代码中...
  • 是的,我很自信,因为我在许多应用程序中都做到了。它不是内置的,您必须在此处提及对 json 的响应,对于 json 请求,您需要在路由中指定格式
  • 感谢 Vishal,在路由中指定格式(这意味着我必须将其添加到所有路由)解决了问题。我添加了 ``` defaults: { format: :json } ``` 到我的路线
  • 是的。你也可以这样做。
  • 想要添加很多人来这个答案将寻找 debug_exception_response_format
【解决方案2】:

您可以使用api_error_handler gem

将其包含在您的捆绑程序文件中:

gem "api_error_handler", "~> 0.2.0"

在您的应用程序控制器中,调用库。

class ApplicationController < ActionController::API
  handle_api_errors(
    # Error handling options go here if you want to override any defaults.
  )

  # ...
end

如果你有这样的控制器:


class UsersController < ApplicationController
  def index
    raise 'SOMETHING WENT WRONG!!!'
  end
end

当您点击此端点时,您将看到此响应

{
  "error": {
    "title": "Internal Server Error",
    "detail": "SOMETHING WENT WRONG!!!"
  }
}

并且状态码将根据您遇到的错误类型设置为适当的状态码。

有关如何配置错误响应的更多信息,请参阅 gem 的 README

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-12-12
    • 2018-12-19
    • 1970-01-01
    • 2018-12-25
    • 1970-01-01
    • 2017-07-07
    • 2014-03-25
    相关资源
    最近更新 更多