捕获JSON请求解析错误并在JSON中返回500响应 - Rails

时间:2015-10-26 08:36:41

标签: ruby-on-rails json

我正在编写Rails API并希望在请求中捕获任何JSON解析错误,并返回格式正确的JSON以及有用的信息。我通过添加一个类来捕获解析错误,尝试了以下解决方案,引用了here

我试图删除在ACCEPT标头中检查JSON格式的if语句,但它仍然无效。我认为该请求甚至不是首先打击这个中间件。

任何帮助将不胜感激。有用的是我应该如何自己调试这个。谢谢。

# in app/middleware/catch_json_parse_errors.rb
class CatchJsonParseErrors
  def initialize(app)
    @app = app
  end

  def call(env)
    begin
      @app.call(env)
    rescue ActionDispatch::ParamsParser::ParseError => error
      if env['HTTP_ACCEPT'] =~ /application\/json/
        error_output = "There was a problem in the JSON you submitted: #{error}"
        return [
          400, { "Content-Type" => "application/json" },
          [ { status: 400, error: error_output }.to_json ]
        ]
      else
        raise error
      end
    end
  end
end

application.rb中

require File.expand_path('../boot', __FILE__)

require 'rails/all'

# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)

module Yomiapp
  class Application < Rails::Application
    # Settings in config/environments/* take precedence over those specified here.
    # Application configuration should go into files in config/initializers
    # -- all .rb files in that directory are automatically loaded.

    # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
    # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
    # config.time_zone = 'Central Time (US & Canada)'

    # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
    # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
    # config.i18n.default_locale = :de

    # Do not swallow errors in after_commit/after_rollback callbacks.
    config.active_record.raise_in_transactional_callbacks = true

    config.middleware.insert_before ActionDispatch::ParamsParser, "CatchJsonParseErrors"

    config.generators do |g|
      g.test_framework :rspec, fixture: true
      g.fixture_replacement :factory_girl, dir: 'spec/factories'
      g.view_specs false
      g.helper_specs false
      g.stylesheets = false
      g.javascripts = false
      g.helper = false
    end

    config.autoload_paths += %W(\#{config.root}/lib)

    config.middleware.insert_before 0, "Rack::Cors" do
      allow do
        origins '*'
        resource '*',
          headers: :any,
          methods: [:get, :post, :delete, :put, :patch, :options],
          max_age: 0
      end
    end

    config.middleware.use ActionDispatch::Flash
  end
end

rake中间件

use Rack::Cors
use ActionDispatch::Static
use Rack::Lock
use #<ActiveSupport::Cache::Strategy::LocalCache::Middleware:0x000001040ce608>
use Rack::Runtime
use ActionDispatch::RequestId
use Rails::Rack::Logger
use ActionDispatch::ShowExceptions
use ActionDispatch::DebugExceptions
use ActionDispatch::RemoteIp
use ActionDispatch::Reloader
use ActionDispatch::Callbacks
use ActiveRecord::Migration::CheckPending
use ActiveRecord::ConnectionAdapters::ConnectionManagement
use ActiveRecord::QueryCache
use CatchJsonParseErrors
use ActionDispatch::ParamsParser
use Rack::Head
use Rack::ConditionalGet
use Rack::ETag
use Warden::Manager
use ActionDispatch::Flash
run Yomiapp::Application.routes

2 个答案:

答案 0 :(得分:0)

好的我不确定发生了什么,但它现在正在工作而没有任何代码更改。如果我弄清楚出了什么问题,我会再次更新。

答案 1 :(得分:0)

我认为您只需要重新启动服务器。仅当您重新启动服务器时,application.rb中的更改才会生效。现在你停止服务器运行rake middleware命令并刷新application.rb并开始正常工作。