Как обработать искаженный json для маршрута с 'defaults: {format:: json}'? - PullRequest
0 голосов
/ 24 сентября 2018

У меня есть URL, который должен принимать только json:

put "/my_url" => "my_controller#my_actio", defaults: {format: :json}

Когда я отправляю на него искаженный json, он вообще не превращается в «действие» и вместо этого выдает исключениегде-то в Rails и, таким образом, мое приложение возвращает ошибку 500. А именно, это неоправданное исключение.

Как я могу это исправить?

Ответы [ 2 ]

0 голосов
/ 24 сентября 2018

Я использовал следующее промежуточное программное обеспечение для этого варианта использования:

В lib / detect_non_json_labeled_json.rb:

class DetectNonJsonLabeledJson
  def initialize(app, opts = {})
    @app = app
    @opts = opts
  end

  def call(env)
    if(
        middleware_applies_to_this_request?(env) &&
        request_contains_non_json_labeled_as_json?(env)
    )
      [
        415,
        { 'Content-Type' => 'application/json' },
        [ { message: 'Invalid POST body.  Must be parseable as JSON' }.to_json ]
      ]

    else
      @app.call(env)
    end
  end

  private

  def middleware_applies_to_this_request?(env)
    env['PATH_INFO'].start_with?( @opts[:target_prefix] )
  end

  def request_contains_non_json_labeled_as_json?(env)
    labeled_as_json?(env) && contains_non_json?(env)
  end

  def labeled_as_json?(env)
    env['CONTENT_TYPE'] == 'application/json'
  end

  def contains_non_json?(env)
    JSON.parse( ActionDispatch::Request.new(env).raw_post )
    false

  rescue JSON::ParserError
    true
  end
end

В application.rb:

require 'detect_non_json_labeled_json'

module YourApplication
  class Application < Rails::Application
    # ...  
    config.middleware.insert_before(
      ActionDispatch::Static,
      DetectNonJsonLabeledJson,
      { target_prefix: '/' }
    )
  end
end

Обратите внимание, что это возвращает статус 415 - неподдерживаемый тип носителя.Если вы хотите вернуть 422, просто замените код в методе вызова.

0 голосов
/ 24 сентября 2018

Чтобы вы вызвали это исключение и вернули 422.

Вам нужно будет создать файл в приложении / промежуточном программном обеспечении, назовем его json_parse_errors.rb

# app/middleware/json_parse_errors.rb
class JsonParseErrors
  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: 422, error: error_output }.to_json ]
        ]
      else
        raise error
      end
    end
  end
end

Inваш application.rb, добавьте следующую строку

config.middleware.use JsonParseErrors
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...