RESTful API किसी चीज़ की अनुपस्थिति का प्रतिनिधित्व करता है


18

एक व्यक्ति ने अपने आत्मा जानवर को चुना है या नहीं, यह पहचानने के लिए एक एपीआई की कल्पना करें। उनके पास केवल शून्य या एक आत्मा जानवर हो सकते हैं।

वर्तमान में:

/person/{id}/selectedSpiritAnimal

जब उन्होंने एक पशु रिटर्न http 200 चुना है और {selectedAnimal:mole}

लेकिन जब उनका कोई चयन नहीं होता है तो यह http 404 लौटता है।

यह मेरी आत्मा के जानवर को दुखी करता है क्योंकि हम एक वैध डोमेन चिंता का प्रतिनिधित्व कर रहे हैं - अभी तक एक एचटीटीपी त्रुटि के रूप में एक आत्मा जानवर का चयन नहीं किया गया है।

इसके अलावा, एक व्यवसाय के रूप में - erm Sprit-Animal-Hampers-R-us - हम यह जानना चाहते हैं कि जब किसी का कोई चयन नहीं होता है तो हम उन्हें संकेत दे सकते हैं।

यहां बेहतर प्रतिक्रिया क्या है:

HTTP 200 और {selectedAnimal:null}

या इससे भी अधिक स्पष्ट

HTTP 200 और {selectedAnimal:null, spiritAnimalSelected: false}

या 404 लौटाना बेहतर है? बहुत पसंद है this image has not yet been uploadedजब एक छवि ऑनलाइन देखने के एक 404 होगा। एक 404 this person has not selected a spirit animalहो सकता है


इस प्रश्न को एक डुप्लिकेट के रूप में प्रस्तावित किया गया है, लेकिन यह प्रश्न एक अन्यथा मान्य URL को संबोधित करता है जब आवेदन को कॉन्फ़िगर किया गया है जो URL का प्रतिनिधित्व करने वाले परिवर्तन की अनुमति नहीं देता है।

जबकि यहाँ मैं देख रहा हूँ कि कैसे एक संसाधन का प्रतिनिधित्व करता है जहाँ संसाधन की अनुपस्थिति सार्थक है। यानी यह क्लाइंट के लिए URL का अनुरोध करने के लिए मान्य है और प्रतिक्रिया है कि आपने सफलतापूर्वक संसाधन का अनुरोध किया है जो किसी चीज की अनुपस्थिति का प्रतिनिधित्व करता है।

इसलिए यह 'व्यावसायिक तर्क' नहीं है, बल्कि ऐसी परिस्थिति है जहाँ किसी चीज़ की अनुपस्थिति का अर्थ है (यह हो सकता है कि मेरे कई सहयोगी तर्क दे रहे हैं कि 404 अभी भी सही है) लेकिन मुझे यकीन नहीं है कि इसे कैसे मैप किया जाए कल्पना।


जवाब चुनना बहुत मुश्किल है। मैंने यहां बातचीत और काम पर चल रहे एक से अधिक बार अपना मन बदल दिया है।

यहाँ मेरे लिए जो चीज़ बसती है, वह यह है कि युक्ति कहती है कि 4xx तब है जब ग्राहक मिट गया है । इस उदाहरण में ग्राहक से कहा गया है कि वह चयनित से एक प्रतिक्रिया की अपेक्षा करे।

मेरे सहयोगियों के बीच आम सहमति है कि यह खराब एपीआई डिजाइन का एक लक्षण है

यह शायद बेहतर होगा कि हम केवल / व्यक्ति / {आईडी} का अनुरोध करें और यह व्यक्ति के लिए लिंक संबंधों का एक सेट लौटाता है ... फिर यदि आपको / selectSpiritAnimal लिंक नहीं दिया गया है (जब किसी व्यक्ति का कोई चयन नहीं है) लेकिन आप वैसे भी बुलाओ तो एक 404 समझ में आता है। या जब आप आंशिक प्रतिक्रियाओं को लागू करते हैं और / व्यक्ति / {आईडी} एक अधिक पूर्ण दस्तावेज़ लौटाते हैं जब तक कि ग्राहक डेटा के सबसेट का अनुरोध नहीं करता है


5
आपने यह नहीं बताया कि आप क्यों मानते हैं कि यह 404 को वापस करने का एक मुद्दा है। एक डोमेन के दृष्टिकोण से, आपको नहीं पता कि आपको 404 या 200 मिला है, जो क्लाइंट लेयर द्वारा एब्स्ट्रैक्ट किया गया है।
विंसेंट सवार्ड

14
या शायद 204 नो-कंटेंट को वापस करना बेहतर है?
पॉल

6
मुझे लगता है कि 404 के साथ मेरी चिंता यह है कि एक विन्यास परिवर्तन को अस्वीकार कर रहा है जो किसी भी आत्मा के जानवर के साथ एक खराब URL टेम्पलेट का परिचय देता है
पॉल

2
@ PaulD'Ambra इसकी कीमत क्या है, इसके लिए मैं नो-कंटेंट का इस्तेमाल नहीं करता। मैंने नहीं देखा है HTTP कोड जावास्क्रिप्ट के सामने से उस तरह से हैंडल किया गया है जैसे XmlHttpRequest दिनों से। लेकिन यह निश्चित रूप से मान्य है।
ब्रैंडन अर्नोल्ड

जवाबों:


24

HTTP 4xx कोड शायद इस परिदृश्य के लिए सही विकल्प नहीं हैं। आप कहते हैं कि शून्य आत्मा वाले जानवर एक वैध स्थिति है, और एपीआई मार्ग person/{id}/selectedSpiritAnimalइस बात का हिसाब रखेगा कि कोई व्यक्ति idऐसा करता है या नहीं।

HTTP 4xx प्रतिक्रियाएं उस स्थिति के लिए आरक्षित होती हैं, जब किसी ग्राहक ने अनुरोध में कुछ गलत किया हो ( मूल युक्ति का w3 संग्रह देखें )। लेकिन ग्राहक एक वैध अनुरोध कर रहा है, चाहे व्यक्ति के idपास आत्मा जानवर हो या न हो ।

इसलिए मैं प्रतिक्रिया में एक ठीक से स्वरूपित JSON बॉडी और एक HTTP 2xx कोड का उपयोग करके दूसरे समाधान की ओर झुकता हूं।

अब अगर आपको ऐसा अनुरोध मिलता है और यह पता चलता है कि व्यक्ति idमौजूद नहीं है, तो 4xx कोड अधिक मायने रखता है।


17
"HTTP 4xx प्रतिक्रियाएं उस स्थिति के लिए आरक्षित हैं जब किसी ग्राहक ने अनुरोध में कुछ गलत किया है"। युक्ति के बारे में आधिकारिक वक्तव्य देते समय, कृपया वास्तविक HTTP युक्ति का संदर्भ दें, न कि (क) इसके ऊपर निर्मित ढांचा, या (ख) एक यादृच्छिक ब्लॉग पोस्ट।
एरिक स्टीन

5
@ EricStein मुझे उस बारे में थोड़ा आलसी महसूस हुआ; समालोचना के लिए धन्यवाद। अपडेट किया गया।
ब्रैंडन अर्नोल्ड

1
मुझे ऐसा लगता है कि यहाँ RFC लिंक एक तरह से परस्पर विरोधी है। एक ओर 4xx भाग कहता है cases in which the client seems to have erred, लेकिन दूसरी ओर 404 सीधे कहता है The server has not found anything matching the Request-URI। आप एक ग्राहक त्रुटि मौजूद नहीं है कि कुछ अनुरोध करने पर विचार कर सकते हैं। मैं समझता हूं कि कोई व्यक्ति मौजूदा बनाम उप सहारा नहीं है, लेकिन वह प्रतिक्रिया संदेश के रूप में इंगित किया जा सकता है। 204 भी प्रासंगिक लगता है, क्योंकि इकाई मौजूद है, लेकिन उप संपत्ति के लिए कोई सामग्री नहीं है।
शॉर्टस्टफसुशी

1
ग्राहक ने कुछ गलत किया; जब यह मौजूद नहीं है, तो यह उपयोगकर्ता के लिए चयनित स्पिरिट एनिमल का अनुरोध करता है। यही कारण है कि 404 का मतलब है ... आपने उस चीज के लिए कहा है जो वहां नहीं है।
एंडी

5
जब मेरा ब्राउज़र सॉफ़्टवेयरइन्जिनियरिंग.स्टैकएक्सचेंज .com/questions/unicorn से अनुरोध करता है, तो यह एक वैध अनुरोध है और फिर भी मुझे अभी भी 404 मिलता है (आईडी "यूनिकॉर्न" के साथ कोई सवाल नहीं होना चाहिए)।
user253751

24

मैं आपको रिचर्डसन परिपक्वता मॉडल से मिलवाता हूं ।

आपकी समस्या यह है कि आप एक के रूप में दो संसाधनों का प्रतिनिधित्व कर रहे हैं, जहां आपको वास्तव में दो संसाधन होने चाहिए जो कि हाइपरमीडिया द्वारा इंगित संबंध है। रिश्तों का वर्णन करने के लिए हाइपरमीडिया का उपयोग करना रेस्ट का शानदार स्तर 3 है।

आपके व्यक्ति को यूआरआई के तहत रहना चाहिए /person/{id}और पशु को नीचे रहना चाहिए /spiritanimal/{id}। व्यक्ति को यह संकेत देना चाहिए कि उसके पास जानवर के लिए लिंक का उपयोग करके आत्मा जानवर है।

आइए एक व्यक्ति बॉब की कल्पना करें, जिसके पास आईडी 123 और एक यूनिकॉर्न स्पिरिट जानवर है।

GET /person/123

लौटूंगा;

{
  "name": "Bob",
  "links": [
    {
      "rel": "spiritanimal",
      "uri": "/spiritanimals/789"
    }
  ]
}

अब जो कोई भी व्यक्ति 123 को पढ़ता है, उसे पता होगा कि उनके पास एक आत्मा का जानवर है, और उनके पास URI है जहां वे इस बारे में अधिक जानकारी प्राप्त कर सकते हैं।

GET /spitiranimal/789

लौट सकता है

{
  "type": "Unicorn"
}

अब फ्रेड नामक एक व्यक्ति की कल्पना करते हैं, जिसके पास आईडी 456 है और कोई आत्मा नहीं है।

GET /person/456

लौटूंगा;

{
  "name": "Fred",
  "links": [
  ]
}

अब कोई भी व्यक्ति जो व्यक्ति 456 पढ़ता है, उसे पता चल जाएगा कि उनके पास कोई आत्मा नहीं है, क्योंकि कोई लिंक नहीं है। रिश्ते की कमी का प्रतिनिधित्व करने के लिए किसी भी HTTP स्थिति कोड का उपयोग करने की आवश्यकता नहीं है।


1
सिर्फ इस सवाल को जोड़ रहा था कि, एपीआई को बदलने की क्षमता को देखते हुए, HATEOAS का कुछ स्तर शायद सही समाधान होगा। इसका एक बड़ा उदाहरण है
पॉल

1

आत्मा के जानवरों को प्राप्त करने के लिए यह उपयुक्त यूआरएल है; इसलिए, एक 404 त्रुटि अनुचित है। 404 एक तकनीकी समस्या का प्रतिनिधित्व करने के लिए है, न कि तर्क समस्या के लिए।

Http 200 और लौटने के लिए उपयुक्त समाधान है {"selectedAnimal": null}

आपके पास एक अलग वेबमैथोड होना चाहिए /person/{id}/hasSelectedSpiritAnimalजो वापस लौटता है {"isSpiritAnimalSelected": false}। पर्दे के पीछे, यह एक ही विधि कॉल कर सकता है या नहीं कर सकता है, बस अगर झूठा वापस आ रहा है, लेकिन यह निर्णय लेने के लिए है, उपभोग कोड नहीं।

ऐसा करने के लिए एक सम्मोहक कारण के बिना एक वेब विधि में अलग-अलग प्रश्नों के संयोजन से बचने के लिए बेहतर है, भले ही प्रश्न निकट से संबंधित हों।


1
क्या आप बता सकते हैं कि आप क्यों मानते हैं कि यह उचित समाधान है? जब कोई डेटा वापस नहीं किया जाता है तो मैं डेटा वापस करने का कोई मतलब नहीं बना सकता। मैं आपसे सहमत हूं कि URL के ठीक होने से 404 का कोई मतलब नहीं है, इसलिए एक 204 मुझे सबसे अधिक समझ में आता है।
विंसेंट सवार्ड

2
@VincentSavard स्थिति कोड जोंस प्रतिक्रियाओं की तुलना में काम करने के लिए अधिक कठिन हैं, और तकनीकी मुद्दों के लिए अधिक उपयुक्त हैं बजाय इसके बाद डोमेन जानकारी का संचार करते हैं।
TheCatWhisperer

2
204: खाली शरीर के साथ कोई सामग्री नहीं । यह सब स्पष्ट और आत्म व्याख्यात्मक है। आगे बहस करने की जरूरत नहीं है। सभी में, जब कोई स्पष्ट डिज़ाइन पैटर्न नहीं होता है, तो एसई को एक को चुनना चाहिए, इसे अपनी आवश्यकता के लिए मोड़ना चाहिए और प्रलेखन प्रदान करना चाहिए। एक 204 प्रतिक्रिया के साथ एक शरीर लौटना परिणामी नहीं है।
फॉर्मिक्सियन

2
@formixian ... यदि आप json / http के बजाय bjson / tcp api बना रहे थे, तो आप इस मामले के लिए क्या लौटाएंगे? Http कोड पर भरोसा करना अनावश्यक रूप से एपीआई के परिणामों को उसके http कार्यान्वयन के लिए बाध्य करता है।
कैटरवर्जर

2
@VincentSavard When you said "the spirit animal is not currently on file", it seemed quite similar to me to "there is no content"कोई भी सामग्री का मतलब कोई सामग्री नहीं है । अर्थात: यह "" लौटाता है। ये दोनों समान नहीं हैं। "आत्मा का जानवर वर्तमान में फ़ाइल में नहीं है" "" से बहुत अलग है।
शेन

1

आपका समापन बिंदु जो प्रतिनिधित्व करता है वह सिर्फ एक जानवर नहीं है; यह एक जानवर है या इसकी कमी है। यह एक Optional/ Maybe/ Nullable/ आदि द्वारा दर्शाया गया सबसे अच्छा मूल्य है ।

तो वैध मूल्य (200 OK में) हो सकते हैं:

  • {'animal': <some animal>, 'selected': true}
  • {'animal': null, 'selected': false}

मैं उस DELETEपद्धति की कल्पना कर सकता हूं , जब एंडपॉइंट पर लागू किया जाता है, फिर से सेट 'selected'हो सकता है false, अर्थात चयनित जानवर को परेशान कर सकता है।

आप निश्चित रूप से 'selected'यहां कुंजी छोड़ सकते हैं, यह केवल स्पष्टता के लिए दिखाया गया है; स्ट्रिंग बनाम nullअंतर के लिए पर्याप्त है।


0

आपको 404 का उपयोग करना चाहिए।

404 (नहीं मिला) स्थिति कोड इंगित करता है कि मूल सर्वर को लक्ष्य संसाधन के लिए वर्तमान प्रतिनिधित्व नहीं मिला

RFC7231

HTTP/1.1 200 OK
Content-Type: application/json
Date: Mon, 25 Sep 2017 00:00:00 GMT

"mole"

HTTP/1.1 404 Not Found
Content-Type: text/plain
Date: Mon, 25 Sep 2017 00:00:00 GMT

this person has not selected a spirit animal

चूंकि आप प्रोग्रामिंग इंटरफ़ेस बना रहे हैं, मानव इंटरफ़ेस नहीं, 404 टेक्स्ट वैकल्पिक है।

मैं इसे पसंद करता हूं क्योंकि मैं यथासंभव मानक प्रोटोकॉल पसंद करता हूं। HTTP के पास गैर-मौजूदगी का प्रतिनिधित्व करने का एक तरीका है, और यही मैं उपयोग करता हूं।

संपादित करें: मान लीजिए कि आपने एक ऐसी सुविधा जोड़ी है जहाँ उपयोगकर्ता यह चुन सकते हैं कि क्या उन्हें अपनी आत्मा के जानवरों को साझा करना है, और किसी ने इसे साझा नहीं किया है। क्या आप 200 ओके null, या 200 ओके लौटाएंगे "Unauthorized? या आप मानक 401 अनधिकृत / 403 निषिद्ध मानक का उपयोग करेंगे? यह पहली जगह में एक का चयन नहीं करने के लिए सीधे अनुरूप लगता है।


वैकल्पिक रूप से, यदि आप 200 OK + JSON का उपयोग करना चाहते हैं, तो आपको वापस लौटना चाहिए null

HTTP/1.1 200 OK
Content-Type: application/json
Date: Mon, 25 Sep 2017 00:00:00 GMT

"mole"

HTTP/1.1 200 OK
Content-Type: application/json
Date: Mon, 25 Sep 2017 00:00:00 GMT

null

चीजों को साफ रखें। अधिक आवश्यक होने पर ही रैपिंग बनाएं।


2
डेटा है , हालांकि पाया,। यह सिर्फ इतना होता है कि डेटा null(कोई मूल्य नहीं है) है। यह क्लाइंट के लिए कुछ अनुरोध करने से अलग है जिसके लिए मान रखने के लिए कोई स्लॉट मौजूद नहीं है। AttributeErrorजब मान होता है तो आप पायथन में फेंकने का सुझाव नहीं देंगे None; यह इंटरफ़ेस को अव्यवहारिक और अनावश्यक रूप से काम करना मुश्किल बना देगा। अधिक व्यावहारिक रूप से, कई HTTP क्लाइंट एपीआई 404 भाषा की मानक त्रुटि हैंडलिंग तंत्र (त्रुटि कोड, अपवाद, त्रुटि प्रकार) में परिवर्तित हो सकते हैं, जिसका अर्थ है कि आपको एक बाहरी त्रुटि को दबाना होगा।
jpmc26

@Paul ड्रेपर को युक्ति में थोड़ा ऊपर स्क्रॉल करें, आप देखेंगे कि यह HTTP 4xx के बारे में एक कंबल बयान करता है: "4xx वर्ग की स्थिति कोड उन मामलों के लिए अभिप्रेत है जिसमें ग्राहक को मिटा दिया गया है।" सेशन में स्पष्ट रूप से कहा गया है कि स्पिरिट एनिमल न होना एक मान्य स्थिति है जिसके लिए एपीआई को हिसाब देना चाहिए। tools.ietf.org/html/rfc7231#section-6.5
ब्रैंडन अर्नोल्ड

फिर, आप अनुरोधित संसाधन (अर्थात कोई पशु चयनित नहीं) के गैर-अस्तित्व को इंगित करने के बीच अंतर करते हैं, और क्लाइंट एक अमान्य पथ का अनुरोध करता है (यानी /person/{id}/selectedSpritAnimal, टाइपो का निरीक्षण करें Sprit)।
संपतश्री

1
इरादे की परवाह किए बिना, 404 सख्ती का मतलब है कि संसाधन नहीं मिला। यदि कोई चयनितSpiritAnimal एक संसाधन है, और कोई भी मौजूद नहीं है, तो GET के लिए कुछ भी नहीं है और एक 404 उपयुक्त है। हालाँकि यदि ग्राहक यह जानना चाहता है कि क्या एक आत्मा जानवर का चयन किया गया था, तो सर्वर को एक अन्य संसाधन को उजागर करना चाहिए /person/{id}/isSpiritAnimalSelectedजो ग्राहक को बताएगा कि क्या एक का चयन किया गया था। मुझे परीक्षण के एक ही क्लासिक उदाहरण लगता है कि क्या कोई फ़ाइल इसे पढ़ने से पहले मौजूद है। बस फ़ाइल को पढ़ें और ENOENT त्रुटि को संभालना चाहिए इसे फेंक दिया जाना चाहिए।
अहाता

1
@PaulDraper यह बात नहीं है कि संसाधन मौजूद है या नहीं। बिंदु HTTP 4xx कोड तब होता है जब कॉलर गलत तरीके से API का उपयोग कर रहा होता है। Op बताता है कि /person/{id}/selectedSpiritAnimalआत्मा जानवर मौजूद नहीं होने के बावजूद इसका उपयोग किया जाना है। इसका मतलब है कि HTTP 4xx गलत है, जब इस तरह के मामले में उपयोग किया जाता है। Op भी सही ढंग से बताता है कि यह खराब API डिज़ाइन की गंध हो सकती है।
ब्रैंडन अर्नाल्ड
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.