Я использовал следующее промежуточное программное обеспечение для этого варианта использования:
В 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, просто замените код в методе вызова.