Rails にJSONでリクエストを投げた際に発生する JSON::ParserError をハンドリングする
何が問題か
API として公開している Rails Server に対して、Invalid な JSON データを送信した場合、 parse error が発生した場合は、適切にリダイレクトやエラーメッセージの制御を行いたい。
だけど、挙動としては、Controller に到達する前の Rack Layer で勝手に parse 処理が走ってしまい、 Rack Layer で raise されて勝手に落ちてしまう。
具体的には ActionDispatch::ParamsParser
が先にパラメータを見ている。
吐かれるログはこんな感じ
Started PUT "/api/users/5001" for ::1 at 2016-07-07 16:24:16 +0900
Error occurred while parsing request parameters.
Contents:
{
"user": {
"email": "sample@example.com",
"password": "cGFzc3dvcmQ=",
"name": "田中太郎"
}
}:
/.rbenv/versions/2.3.1/lib/ruby/2.3.0/json/common.rb:156:in `parse'
activesupport (4.2.4) lib/active_support/json/decoding.rb:26:in `decode'
actionpack (4.2.4) lib/action_dispatch/middleware/params_parser.rb:44:in `parse_formatted_parameters'
ログに生情報がそのまま出てしまうし、リクエスト元にも同じ内容が返ってしまう。 さらに、リダイレクトやエラーメッセージの表示を制御できないのもマズい。
どうすればいいのか
middleware のスタックに、ActionDispatch::ParamsParser
よりも前にハンドリング用の middleware を差し込む。
今回自分は Committeeという Gem を使っていて、この Gem で定義されている ハンドリング処理に任せたかったので、
application.rb
では以下のように指定した
config.middleware.insert_before ActionDispatch::ParamsParser, Committee::Middleware::RequestValidation, schema: JSON.parse(File.read(schema_file))
config.middleware.insert_before ActionDispatch::ParamsParser, Committee::Middleware::ResponseValidation, schema: JSON.parse(File.read(schema_file))