2016-12-16 16 views
4

私はRails 5を使用していますが、APIに対する無効なJSONリクエストのエラー処理を改善しようとしています。ラックミドルウェアで無効なJSON解析エラーをキャッチ

コントローラでレスキューを解析して無効な形式のJSONを処理しようとしましたが、ユーザがコンテンツヘッダをリクエストヘッダに追加した場合、Railsミドルウェアがコントローラにヒットする前にJSON要求を解析しています。

.rbenv /バージョン/ 2.3.1/libに/ルビー/宝石/ 2.3:サーバを起動するときに、私は次のエラーを取得する、しかし https://robots.thoughtbot.com/catching-json-parse-errors-with-custom-middleware

は、私は、以下のガイドに従っ0.0 /宝石/ actionpack-5.0.0.1/libに/ action_dispatch /ミドルウェア/ stack.rb:108: `assert_index '内:前に挿入する、そのようなミドルウェア:ActionDispatch :: ParamsParser(例外RuntimeError)今

、これが意味することは、ActionD ispatch :: ParamsParserは実行されていません。私は、Rails 5では廃止されているので、そのオプションを除外していると思います。

私も自分のAPIコントローラでrescue_fromを使用しようとしました:

rescue_from JSON::ParserError, with: :json_error 

def json_error 
    render status: 400, json: {error: "Invalid JSON format in request body"}, status: :unprocessable_entity 
end 

しかし、これもうまくいきませんでした。それは過去をスキップするようです。

または私はこのしようとした場合:

rescue_from JSON::ParserError, with: json_error 

def json_error 
    render status: 400, json: {error: "Invalid JSON format in request body"}, status: :unprocessable_entity 
end 

を私が手:

undefined local variable or method `json_error' for Api::ApiController:Class 
actionpack (5.0.0.1) lib/action_dispatch/routing/route_set.rb, line 46 

``` ruby 
    41   private 
    42 
    43   def controller(req) 
    44    req.controller_class 
    45   rescue NameError => e 
> 46    raise ActionController::RoutingError, e.message, e.backtrace 
    47   end 
    48 
    49   def dispatch(controller, action, req, res) 
    50    controller.dispatch(action, req, res) 
    51   end 

は非常に失われたガイドは、いくつかのガイダンス

+0

あなたがプロジェクトに 'アプリ/ミドルウェア/ catch_json_parse_errors.rb'を追加しましたか?それよりも、 'app/middleware'はあなたのアプリケーションの' autoload_paths'にあるべきです。 – 0xd

+0

はい、ファイルを追加しました。エラーは、私のクラスではなくActionDispatch :: ParamsParserに関連しています – pronoob

答えて

11

を使用することができます上記のガイドは、後レール5と古いようですいくつかの調査では、次のミドルウェアはもはや呼び出されていないようです:

のconfig/application.rb

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

私はそれがために変更は:ラック::頭がミドルウェア・スタックであるが、ActionDispatch :: ParamsParserではないので

require "./lib/middleware/catch_json_parse_errors.rb" 
config.middleware.insert_before Rack::Head, CatchJsonParseErrors 

です。また、クラス名を文字列として使用することは推奨されていないため、ファイルを要求してからクラスを渡す必要があります。

私もENVをチェックするには、以下のクラスを修正代わりにENVの[ 'CONTENT_TYPE'] [ 'HTTP_ACCEPT']

class CatchJsonParseErrors 
    def initialize(app) 
    @app = app 
    end 

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

なぜHTTP_ACCEPTをCONTENT_TYPEに変更しましたか? Accept-Headerはクライアントが返すことを期待しているものを定義しているのに対し、ContentTypeは何が入ってくるのかを定義しているので、正しい情報源のようです(* response *の形式とは関係ありません)。 –

+0

@AndreasBaumgartこれは、このミドルウェアが応答ではなく無効なjson要求をチェックするためです。しかし、私は受け入れのヘッダーに既存のチェックを維持することをお勧めします。 – Andy

関連する問題