REST API एरर रिस्पांस मॉडल और एरर कोड सिस्टम बनाने का सबसे अच्छा तरीका क्या है?


15

मेरा REST कार्यान्वयन JSON में अगली संरचना के साथ त्रुटियां लौटाएगा:

{
 "http_response":400,
 "dev_message":"There is a problem",
 "message_for_user":"Bad request",
 "some_internal_error_code":12345
}

मैं विशेष प्रतिक्रिया मॉडल बनाने का सुझाव देता हूं, जहां मैं गुणों के लिए आवश्यक मान पारित कर सकता हूं (dev_message, message_for_user, some_internal_error_code), और उन्हें वापस कर सकता हूं। कोड में यह इस तरह होगा:

$responseModel = new MyResponseModel(400,"Something is bad", etc...);

यह मॉडल कैसा दिखना चाहिए? क्या मुझे तरीकों को लागू करना चाहिए जैसे कि successResponse () जहाँ मैं केवल पाठ जानकारी पास करूँगा, और वहाँ कोड 200 डिफ़ॉल्ट होगा? इससे मैं फंसा हुआ हूं। और यह मेरे सवाल का पहला हिस्सा है: क्या मुझे इस मॉडल को लागू करने की आवश्यकता है, क्या यह अच्छा अभ्यास है? क्योंकि अभी के लिए, मैं कोड से सीधे सरणियाँ लौटा रहा हूं।

दूसरा भाग एरर कोड सिस्टम के बारे में है। त्रुटि कोड प्रलेखन में वर्णित किया जाएगा। लेकिन मुझे जो समस्या आ रही है वह कोड में है। त्रुटि कोड को प्रबंधित करने का सबसे अच्छा तरीका क्या है? क्या मुझे उन्हें मॉडल के अंदर लिखना चाहिए? या इससे निपटने के लिए अलग से सर्विस बनाना बेहतर होगा?

अद्यतन १

मैंने प्रतिक्रिया के लिए मॉडल वर्ग लागू किया है। यह समान ग्रेग के जवाब है, एक ही तर्क है, लेकिन additionaly मैं है hardcoded लिखा मॉडल में त्रुटियों और यहाँ यह है कि यह कैसे की तरह लग रहा है:

    class ErrorResponse
    {
     const SOME_ENTITY_NOT_FOUND = 100;
     protected $errorMessages = [100 => ["error_message" => "That entity doesn't exist!"]];

     ...some code...
    }

मैंने ऐसा क्यों किया? और किस लिए?

  1. यह कोड में अच्छा लग रहा है: return new ErrorResponse(ErrorResponse::SOME_ENTITY_NOT_FOUND );
  2. त्रुटि संदेश बदलने में आसान। सभी संदेश नियंत्रक / सेवा / आदि के बजाय एक जगह पर हैं या जो कुछ भी आपने इसे रखा है।

यदि आपके पास इसे सुधारने के लिए कोई सुझाव है, तो कृपया टिप्पणी करें।

जवाबों:


13

इस स्थिति में, मैं हमेशा पहले इंटरफ़ेस के बारे में सोचता हूं, फिर समर्थन करने के लिए PHP कोड लिखता हूं।

  1. यह एक वास्तविक एपीआई है, इसलिए सार्थक HTTP स्थिति कोड एक होना चाहिए।
  2. आप क्लाइंट से लगातार और लचीली डेटा संरचनाएँ भेजना चाहते हैं।

आइए उन सभी चीजों के बारे में सोचें जो गलत हो सकती हैं और उनके HTTP स्टेटस कोड:

  • सर्वर एक त्रुटि फेंकता है (500)
  • प्रमाणीकरण विफलता (401)
  • अनुरोधित संसाधन नहीं मिला (404)
  • आपके द्वारा लोड किए जाने के बाद से आपके द्वारा संशोधित किए जा रहे डेटा को बदल दिया गया है (409)
  • डेटा की बचत करते समय सत्यापन त्रुटियां (422)
  • ग्राहक ने अपने अनुरोध दर को पार कर लिया है (429)
  • असमर्थित फ़ाइल प्रकार (415)

ध्यान दें, कुछ अन्य हैं जो आप बाद में शोध कर सकते हैं।

अधिकांश विफलता स्थितियों के लिए, केवल एक त्रुटि संदेश वापस करना है। 422 Unprocessable Entityप्रतिक्रिया है, जो मैं "सत्यापन त्रुटियों के लिए" का उपयोग किया है और अधिक से अधिक एक त्रुटि --- फॉर्म फील्ड प्रति एक या अधिक त्रुटियां लौट सकते हैं।

हमें त्रुटि प्रतिक्रियाओं के लिए एक लचीली डेटा संरचना की आवश्यकता है।

एक उदाहरण के रूप में लें 500 Internal Server Error:

HTTP/1.1 500 Internal Server Error
Content-Type: text/json
Date: Fri, 16 Jan 2015 17:44:25 GMT
... other headers omitted ...

{
    "errors": {
        "general": [
            "Something went catastrophically wrong on the server! BWOOP! BWOOP! BWOOP!"
        ]
    }
}

सर्वर के लिए कुछ पोस्ट करने की कोशिश करते समय सरल सत्यापन त्रुटियों के साथ विरोध करें:

HTTP/1.1 422 Unprocessable Entity
Content-Type: text/json
Date: Fri, 16 Jan 2015 17:44:25 GMT
... other headers omitted ...

{
    "errors": {
        "first_name": [
            "is required"
        ],
        "telephone": [
            "should not exceed 12 characters",
            "is not in the correct format"
        ]
    }
}

वे कुंजी यहाँ सामग्री प्रकार है text/json। यह क्लाइंट एप्लिकेशन को बताता है कि वे JSON डिकोडर के साथ प्रतिक्रिया बॉडी को डीकोड कर सकते हैं। यदि कहते हैं, एक आंतरिक सर्वर त्रुटि पकड़ा नहीं है और अपने सामान्य "कुछ गलत हो गया" वेब पेज के बजाय दिया जाता है, सामग्री प्रकार होना चाहिएtext/html; charset=utf-8 ताकि क्लाइंट एप्लिकेशन प्रतिक्रिया बॉडी को JSON के रूप में डिकोड करने का प्रयास न करें।

जब तक आपको JSONP प्रतिक्रियाओं का समर्थन करने की आवश्यकता होती है, तब तक यह सभी खोज और बांका दिखता है । आपको 200 OKविफलताओं के लिए भी एक प्रतिसाद देना चाहिए । इस स्थिति में आपको पता लगाना होगा कि क्लाइंट JSONP रिस्पांस का अनुरोध कर रहा है (आमतौर पर URL अनुरोध पैरामीटर का पता लगाने के लिए)callback ) और डेटा संरचना को थोड़ा बदलकर:

(GET / पोस्ट / 123; कॉलबैक = डिस्प्लेब्लॉगपोस्ट)

<script type="text/javascript" src="/posts/123?callback=displayBlogPost"></script>

HTTP/1.1 200 OK
Content-Type: text/javascript
Date: Fri, 16 Jan 2015 17:44:25 GMT
... other headers omitted ...

displayBlogPost({
    "status": 500,
    "data": {
        "errors": {
            "general": [
                "Something went catastrophically wrong on the server! BWOOP! BWOOP! BWOOP!"
            ]
        }
    }
});

फिर क्लाइंट पर प्रतिक्रिया हैंडलर (एक वेब ब्राउज़र में) में एक वैश्विक जावास्क्रिप्ट फ़ंक्शन होना चाहिए जिसे displayBlogPostएक एकल तर्क स्वीकार किया जाता है। यदि प्रतिक्रिया सफल थी, तो यह फ़ंक्शन निर्धारित करना होगा:

function displayBlogPost(response) {
    if (response.status == 500) {
        alert(response.data.errors.general[0]);
    }
}

इसलिए हमने ग्राहक का ध्यान रखा है। अब, चलो सर्वर का ख्याल रखें।

<?php

class ResponseError
{
    const STATUS_INTERNAL_SERVER_ERROR = 500;
    const STATUS_UNPROCESSABLE_ENTITY = 422;

    private $status;
    private $messages;

    public function ResponseError($status, $message = null)
    {
        $this->status = $status;

        if (isset($message)) {
            $this->messages = array(
                'general' => array($message)
            );
        } else {
            $this->messages = array();
        }
    }

    public function addMessage($key, $message)
    {
        if (!isset($message)) {
            $message = $key;
            $key = 'general';
        }

        if (!isset($this->messages[$key])) {
            $this->messages[$key] = array();
        }

        $this->messages[$key][] = $message;
    }

    public function getMessages()
    {
        return $this->messages;
    }

    public function getStatus()
    {
        return $this->status;
    }
}

और सर्वर त्रुटि के मामले में इसका उपयोग करने के लिए:

try {
    // some code that throws an exception
}
catch (Exception $ex) {
    return new ResponseError(ResponseError::STATUS_INTERNAL_SERVER_ERROR, $ex->message);
}

या उपयोगकर्ता इनपुट को मान्य करते समय:

// Validate some input from the user, and it is invalid:

$response = new ResponseError(ResponseError::STATUS_UNPROCESSABLE_ENTITY);
$response->addMessage('first_name', 'is required');
$response->addMessage('telephone', 'should not exceed 12 characters');
$response->addMessage('telephone', 'is not in the correct format');

return $response;

उसके बाद, आपको बस कुछ ऐसा चाहिए जो लौटी हुई प्रतिक्रिया वस्तु लेता है और इसे JSON में रूपांतरित करता है और प्रतिक्रिया को उसके मीरा मार्ग पर भेजता है।


उत्तर के लिए धन्यवाद! मैंने इसी तरह का समाधान लागू किया है। एकमात्र अंतर यह है कि मैं किसी भी संदेश को खुद से पारित नहीं करता हूं, वे पहले से ही सेट हैं (मेरे अपडेट किए गए प्रश्न देखें)।
Grokking

-2

मैं कुछ इसी तरह का सामना कर रहा था, मैंने 3 चीजें कीं,

  1. खुद के लिए एक एक्ससेप्शनहैंडलर बनाया जिसे एबीसीसीसेप्शन कहा जाता है।

चूंकि मैं जावा और स्प्रिंग का उपयोग कर रहा हूं,

मैंने इसे परिभाषित किया

 public class ABCException extends Exception {
private String errorMessage;
private HttpStatus statusCode;

    public ABCException(String errorMessage,HttpStatus statusCode){
            super(errorMessage);
            this.statusCode = statusCode;

        }
    }

फिर आवश्यकता पड़ने पर इसे इस तरह बुलाया,

throw new ABCException("Invalid User",HttpStatus.CONFLICT);

और हाँ आपको अपने कंट्रोलर में एक एक्ससेप्शनहैंडलर बनाने की ज़रूरत है अगर आप REST पर आधारित वेबसाइट का उपयोग कर रहे हैं।

@ExceptionHandlerअगर वसंत का उपयोग कर के साथ यह एनोटेट


प्रोग्रामर वैचारिक प्रश्नों के बारे में हैं और चीजों की व्याख्या करने के लिए उत्तर अपेक्षित हैं । स्पष्टीकरण के बजाय कोड डंप फेंकना आईडीई से व्हाइटबोर्ड पर कोड कॉपी करने जैसा है: यह परिचित लग सकता है और यहां तक ​​कि कभी-कभी समझ में आता है, लेकिन यह अजीब लगता है ... बस अजीब है। व्हाइटबोर्ड में कंपाइलर नहीं है
gnat
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.