2012-08-08 14 views
32

मेरे पास "एक सेवा के रूप में सॉफ्टवेयर" ऐप है जो एक RESTful API के माध्यम से जेएसओएन संचारित करता है।जेएसओएन आधारित रीस्टफुल कोड में अपवादों को कैसे संभालें?

बस कहा गया: JSON डेटा इंटरचेंज के साथ एक विश्वसनीय API का उपयोग करते समय अपवादों को कैप्चर करने और रिपोर्ट करने के लिए सर्वोत्तम प्रथाएं क्या हैं?

मेरा पहला विचार यह देखना था कि रेल मचान पैदा करके क्या करता है, लेकिन यह स्पष्ट रूप से सही नहीं है। JSON कोड किसी गैर-मौजूद आईडी भेजता है, तो

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 

इस मामले में, उदाहरण के लिए: यहाँ एक अंश है

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

तो Mumble.find() ActiveRecord :: RecordNotFound बढ़ाएगा। ActionController उसे पकड़ लेगा और HTML में एक त्रुटि पृष्ठ प्रस्तुत करेगा। लेकिन एचटीएमएल क्लाइंट के लिए बेकार है जो JSON की अपेक्षा कर रहा है।

मैं begin ... rescue RuntimeError ब्लॉक में Mumble.find() को लपेटकर और JSON स्थिति =>: unprocessable_entity या कुछ प्रस्तुत करने के द्वारा उस पर काम कर सकता हूं।

लेकिन तब क्या ग्राहक की एप्लिकेशन गलत पथ, उदा .:

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

एक JSON आधारित एप्लिकेशन कि पकड़ने और JSON में कोई त्रुटि वापस जाने के लिए माना जाता है भेजता है? यदि हां, तो मैं एक्शन डिस्पैच में गहरी खुदाई के बिना कहां कैप्चर करूं?

तो कुल मिलाकर, क्या मैं पंट करता हूं और अगर कोई त्रुटि हो तो एक्शनकंट्रोलर HTML उत्पन्न करता है? यह सही लगता है नहीं ...

उत्तर

71

(मैं इस सवाल का जवाब मिल गया बस से पहले मैं [अपने प्रश्न पोस्ट] टक्कर मार दी। लेकिन इस किसी और रूप में अच्छी तरह मदद कर सकता है ...)

जवाब ActionController के उपयोग करने के लिए है rescue_from, जैसा कि in 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 एपीआई कोड लिखने के लिए एक सुसंगत मानक रखने के लिए पर कोई स्पष्ट आम सहमति है, लेकिन यह कुछ है जो मैं अभ्यास करता हूं (जो आपने पूछा है उससे अधिक):

  1. इसे आसान रखें - आराम से रहने का प्रयास करें। कस्टम तरीके चीजों को जटिल बना सकते हैं।
  2. सर्वर को मूल त्रुटि कोड लौटाएं, और कैप्चर करने के लिए 'save_from' का उपयोग करें, और
  3. अन्य मामलों में, रेल HTTP HTTP कोड प्रदान करें, जिसे क्लाइंट ऐप द्वारा विशेष रूप से लक्षित किया जा सकता है।

आपके मामले में, आपको रेल के उत्तर_to और answer_with एचटीएमएल/जेसन/अन्य प्रतिक्रियाओं को अनुग्रह के साथ संभाल सकता है। और यहां तक ​​कि आपके समाधान में, यह अभी भी प्रभावी रूप से HTML को प्रस्तुत करेगा, लेकिन यह आपके क्लाइंट ऐप द्वारा व्याख्या नहीं किया जाएगा, जो इसके बजाय HTTP शीर्षलेख पढ़ेगा और HTTP प्रतिक्रिया कोड प्राप्त करेगा, जो आपके 'rescue_from' को ट्रिगर कर रहा है ।

5

यह किसी को भी मदद करता है, तो यह है कि क्या मैं अपने विशुद्ध रूप से json एपीआई के लिए सभी एक पकड़ने के रूप में किया है:

अपने ApplicationController है जो प्रत्येक विशिष्ट नियंत्रक से विरासत में,

# app/controllers/api/v1/application_controller.rb 

# ... 

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

# ... 
  • ज्यादातर आधारित जोड़ने डरलेस_फूल के जवाब से
+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 
संबंधित मुद्दे