2012-08-08 24 views
32

私は、RESTful API経由で通信されたJSONを使用する「サービスとしてのソフトウェア」アプリケーションを持っています。JSONベースのRESTfulコードで例外を処理する方法は?

JSONデータ交換でRESTful APIを使用する場合の例外のキャプチャとレポートのベストプラクティスは何ですか?

私の最初の考えは、Railsが足場を生成することを確認することでしたが、それは明らかに正しくありません。以下は抜粋です:

class MumblesController < ApplicationController 

    # GET /mumbles/1 
    # GET /mumbles/1.json 
    def show 
    @mumble = Mumble.find(params[:id]) 
    respond_to do |format| 
     format.html # show.html.erb 
     format.json { render json: @mumble } 
    end 
    end 

end 

この場合、JSONコードが存在しないIDを送信すると、

http://www.myhost.com/mumbles/99999.json 

次に、Mumble.find()はActiveRecord :: RecordNotFoundを発生させます。 ActionControllerはそれを捕捉し、HTMLでエラーページをレンダリングします。しかし、JSONを期待しているクライアントにとってHTMLは役に立ちません。

begin ... rescue RuntimeErrorブロックにMumble.find()をラップし、JSONステータス=>:unprocessable_entityなどをレンダリングすることで回避できます。

しかし、その後、どのようなクライアントのアプリケーションは、例えば、無効なパスを送る。:

http://www.myhost.com/badtypo/1.json 

場合がJSONベースのアプリケーションはそれをキャッチし、JSONでエラーを返すことになっていますか?もしそうなら、ActionDispatchを深く掘り下げずにどこをキャプチャしますか?

全体的に、私はパントして、エラーがあればActionControllerにHTMLを生成させますか?それは、答えはActionControllerのを使用することです

(私は[あなたの質問を投稿]打つ直前に答えを見つけた。しかし、これは、同様に他の誰かを助けるかもしれない...)...

答えて

71

を右に感じることはありません。 rescue_fromin this Guideと記載され、hereと記載されている。具体的には、デフォルトの404.htmlのデフォルトのレンダリングを交換し、これらの線に沿ってファイルを500.htmlことができます。

class ApplicationController < ActionController::Base 
    rescue_from ActiveRecord::RecordNotFound, :with => :record_not_found 

private 
    def record_not_found(error) 
    render :json => {:error => error.message}, :status => :not_found 
    end 
end 
+1

用心:少なくともレール4で、rescue_from' 'の一致順序は、*通常の' rescue'から*逆転されています。あなたは、サブクラスの対ごとに異なる振る舞いをしたい場合その親クラスは、サブクラス*を親の後に置いてください。 ': - /' – AlexChaffee

1

JSON APIコードを書くための一貫した基準を維持する方法については明確なコンセンサスはありませんが、これは私が練習したもののいくつかです(あなたが求めたもの以上):

  1. 簡単にしてください - 安らかにしてください。カスタムメソッドは物事を複雑にすることができます。
  2. サーバにネイティブエラーコードを返し、キャプチャには「rescue_from」を使用し、その他の場合には
  3. をレンダリングし、レンダリングHTTPレスポンスコードをレンダリングします。

あなたのケースでは、Rails respond_toとrespond_with handle html/json /その他の応答をgraceで見つけることができます。あなたのソリューションでさえ、それでもHTMLを効果的にレンダリングしますが、それはあなたのクライアントアプリケーションによって解釈されるものではなく、代わりにHTTPヘッダーを読んでHTTP応答コードを取得します。これはあなたの 'rescue_from' 。

5

それが誰を助けている場合、これは私が私の純粋なJSON APIのすべてのキャッチとして何をしたかである:あなたのApplicationController

それぞれ特定のコントローラから継承することを、

主に基づいて、
# app/controllers/api/v1/application_controller.rb 

# ... 

rescue_from StandardError do |exception| 
    render json: { :error => exception.message }, :status => 500 
end 

# ... 
  • を追加off fearless_foolの答え
+0

これは、レスキューされたエラーのために500を使って過度に応答しているようです。 –

2

開発者は、トレースを表示することをお勧めしますミズ)。そして、生産のためのトレースを不可視:

rescue_from StandardError do |exception| 
    # Handle only JSON requests 
    raise unless request.format.json? 

    err = {error: exception.message} 

    err[:backtrace] = exception.backtrace.select do |line| 
     # filter out non-significant lines: 
     %w(/gems/ /rubygems/ /lib/ruby/).all? do |litter| 
     not line.include?(litter) 
     end 
    end if Rails.env.development? and exception.is_a? Exception 

    # duplicate exception output to console: 
    STDERR.puts ['ERROR:', err[:error], ''] 
        .concat(err[:backtrace] || []).join "\n" 

    render :json => err, :status => 500 
    end 
関連する問題