REST - शरीर में ID डालते हैं या नहीं?


95

मान लीजिए कि मैं लोगों के लिए एक RESTful संसाधन रखना चाहता हूं, जहां क्लाइंट आईडी असाइन करने में सक्षम है।

एक व्यक्ति इस तरह दिखता है: {"id": <UUID>, "name": "Jimmy"}

अब, ग्राहक को कैसे बचाना चाहिए (या "PUT") इसे?

  1. PUT /person/UUID {"id": <UUID>, "name": "Jimmy"} - अब हमारे पास यह गंदा दोहराव है जिसे हमें हर समय सत्यापित करना होगा: क्या शरीर में आईडी पथ में मेल खाती है?
  2. असममित प्रतिनिधित्व:
    • PUT /person/UUID {"name": "Jimmy"}
    • GET /person/UUID रिटर्न {"id": <UUID>, "name": "Jimmy"}
  3. शरीर में कोई आईडी नहीं - केवल स्थान में आईडी:
    • PUT /person/UUID {"name": "Jimmy"}
    • GET /person/UUID रिटर्न {"name": "Jimmy"}
  4. POSTक्लाइंट द्वारा आईडी तैयार किए जाने के बाद से किसी भी तरह का कोई अच्छा विचार नहीं है।

इसे हल करने के सामान्य पैटर्न और तरीके क्या हैं? केवल स्थान पर आईडी ही सबसे हठधर्मी तरीके से सही लगती हैं, लेकिन यह व्यावहारिक कार्यान्वयन को भी कठिन बना देती है।

जवाबों:


62

अलग-अलग पढ़ने / लिखने के मॉडल होने में कुछ भी गलत नहीं है: ग्राहक एक संसाधन प्रतिनिधित्व लिख सकता है, जहां सर्वर द्वारा जोड़े गए / परिकलित तत्वों के साथ एक और प्रतिनिधित्व वापस कर सकते हैं (या यहां तक ​​कि पूरी तरह से अलग प्रतिनिधित्व भी - इसके खिलाफ किसी भी कल्पना में कुछ भी नहीं है केवल आवश्यकता यह है कि PUT को संसाधन बनाना या बदलना चाहिए)।

इसलिए मैं (2) में असममित समाधान के लिए जाऊंगा और लिखते समय सर्वर साइड पर "गंदा डुप्लिकेट चेक" से बचूंगा:

PUT /person/UUID {"name": "Jimmy"}

GET /person/UUID returns {"id": <UUID>, "name": "Jimmy"}

1
और यदि आप टाइपिंग (स्थैतिक या गतिशील) लागू करते हैं, तो आप बिना आईडी के मॉडल नहीं बना सकते हैं ... इसलिए PUT अनुरोधों के लिए URL से ID निकालना बहुत आसान है। यह "आराम" नहीं होगा, लेकिन यह सही होगा।
इवान क्लेशानिन

1
idआईडी और इकाई के साथ टीओ के साथ बिना अतिरिक्त अतिरिक्त रखें और प्रोग्रामर के लिए अतिरिक्त कन्वर्टर्स और बहुत बड़ा ओवरहेड।
ग्रिगोरी किसलिन

क्या होगा अगर मुझे बॉडी से आईडी मिलती है: PUT / व्यक्ति {"id": 1, "नाम": "जिमी"}। क्या यह एक बुरा अभ्यास होगा?
ब्रूनो सैंटोस

शरीर में आईडी लगाना ठीक रहेगा। पूर्णांक के बजाय ID के लिए GUID का उपयोग करें - अन्यथा आप डुप्लिकेट आईडी के जोखिम को चलाते हैं।
जोर्न वाइल्ड

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

26

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

मेरा मतलब है कि आपको 1 और 2 दोनों का समर्थन करना चाहिए। मैं मानता हूं कि 3 का कोई मतलब नहीं है।

1 और 2 दोनों का समर्थन करने का तरीका यह है कि आईडी को url से प्राप्त किया जाए यदि अनुरोध निकाय में किसी को भी आपूर्ति नहीं की जाती है, और यदि यह अनुरोध निकाय में है, तो मान्य करें कि यह URL में आईडी से मेल खाता है। यदि दोनों मेल नहीं खाते हैं, तो एक 400 खराब अनुरोध प्रतिक्रिया वापस करें।

जब कोई व्यक्ति संसाधन लौटाता है तो रूढ़िवादी हो जाता है और हमेशा आईडी को json में शामिल करता है, भले ही यह पुट में वैकल्पिक हो।


3
यह स्वीकृत समाधान होना चाहिए। एक एपीआई हमेशा उपयोगकर्ता के अनुकूल होना चाहिए। यह शरीर में वैकल्पिक होना चाहिए। मुझे POST से ID प्राप्त नहीं करनी चाहिए और फिर इसे PUT में अपरिभाषित करना होगा। साथ ही, बनाया गया 400 रेस्पॉन्स पॉइंट सही है।
माइकल

लगभग 400 कोड भी सॉफ्टवेयरइंजीनियरिंग.स्टैकएक्सचेंज . com/ questions/ 329229/… चर्चा को देखते हैं । संक्षेप में एक 400 कोड अनुचित नहीं है, बस कम विशिष्ट है, 422 की तुलना करें।
ग्रिगोरी किसलिन

8

इस समस्या का एक समाधान "हाइपरटेक्स्ट के इंजन राज्य के रूप में," या "हेटोस" की कुछ भ्रामक अवधारणा शामिल है। इसका अर्थ है कि एक REST प्रतिक्रिया में हाइपरलिंक के रूप में किए जाने वाले उपलब्ध संसाधन या क्रियाएं शामिल हैं। इस पद्धति का उपयोग करना, जो कि REST की मूल अवधारणा का हिस्सा था, संसाधनों की विशिष्ट पहचानकर्ता / आईडी स्वयं हाइपरलिंक हैं। इसलिए, उदाहरण के लिए, आप कुछ ऐसा कर सकते हैं:

GET /person/<UUID> {"person": {"location": "/person/<UUID>", "data": { "name": "Jimmy"}}}

फिर, यदि आप उस संसाधन को अपडेट करना चाहते हैं, तो आप (pseudocode) कर सकते हैं:

updatedPerson = person.data
updatedPerson.name = "Timmy"
PUT(URI: response.resource, data: updatedPerson)

इसका एक फायदा यह है कि ग्राहक को यूजर आईडी के सर्वर के आंतरिक प्रतिनिधित्व के बारे में कोई जानकारी नहीं होती है। आईडी बदल सकते हैं, और यहां तक ​​कि स्वयं URL भी बदल सकते हैं, जब तक कि क्लाइंट के पास उन्हें खोजने का एक तरीका है। उदाहरण के लिए, जब लोगों का संग्रह हो रहा हो, तो आप इस तरह से प्रतिक्रिया दे सकते हैं:

GET /people
{ "people": [
    "/person/1",
    "/person/2"
  ]
}

(आप, निश्चित रूप से, आवेदन की जरूरतों के आधार पर प्रत्येक व्यक्ति के लिए पूर्ण व्यक्ति वस्तु भी लौटा सकते हैं)।

इस पद्धति के साथ, आप संसाधनों और स्थानों के संदर्भ में अपनी वस्तुओं के बारे में अधिक सोचते हैं, और आईडी के संदर्भ में कम। अद्वितीय पहचानकर्ता का आंतरिक प्रतिनिधित्व इस प्रकार आपके ग्राहक तर्क से अलग हो जाता है। यह REST के पीछे मूल आवेग था: क्लाइंट-सर्वर आर्किटेक्चर बनाने के लिए जो HTTP की सुविधाओं का उपयोग करके पहले से मौजूद RPC प्रणालियों की तुलना में अधिक शिथिल हैं। HATEOAS की अधिक जानकारी के लिए, विकिपीडिया लेख के साथ-साथ इस लघु लेख को भी देखें


4

एक प्रविष्टि में आपको URL में आईडी जोड़ने की आवश्यकता नहीं है। इस तरह यदि आप एक PUT में एक आईडी भेजते हैं तो आपको प्राथमिक कुंजी को बदलने के लिए UPDATE के रूप में व्याख्या की जा सकती है।

  1. दर्ज करें:

    PUT /persons/ 
      {"id": 1, "name": "Jimmy"}
    HTTP/1.1 201 Created     
      {"id": 1, "name": "Jimmy", "other_field"="filled_by_server"}
    
    GET /persons/1
    
    HTTP/1.1 200 OK
      {"id": 1, "name": "Jimmy", "other_field"="filled_by_server"}  
    
  2. अपडेट करें

    PUT /persons/1 
         {"id": "2", "name": "Jimmy Jr"} - 
    HTTP/1.1 200 OK
         {"id": "2", "name": "Jimmy Jr", "other_field"="filled_by_server"}
    
    GET /persons/2 
    
    HTTP/1.1 200 OK
         {"id": "2", "name": "Jimmy Jr", "other_field"="updated_by_server"}
    

JSON एपीआई इस मानक और हल करती है कुछ नई वस्तु के लिंक के साथ डाला जाता है या अद्यतन वस्तु लौटने मुद्दों का उपयोग करता है। कुछ अपडेट या आवेषण में कुछ व्यावसायिक तर्क शामिल हो सकते हैं जो अतिरिक्त फ़ील्ड बदल देंगे

आप यह भी देखेंगे कि आप डालने के बाद और अपडेट से बच सकते हैं।


3

यह पहले पूछा गया है - चर्चा देखने लायक है:

क्या किसी RESTful GET प्रतिसाद को संसाधन की ID लौटा देनी चाहिए?

यह उन सवालों में से एक है जहां यह बहस में फंसना आसान है कि क्या है और "रेस्टफुल" नहीं है

इसके लायक क्या है, मैं लगातार संसाधनों के संदर्भ में सोचने की कोशिश करता हूं और तरीकों के बीच उनके डिजाइन को नहीं बदलता। हालाँकि, प्रयोज्य दृष्टिकोण से IMHO सबसे महत्वपूर्ण बात यह है कि आप संपूर्ण API पर संगत हैं!


3

सिर्फ FYI करें, यहाँ उत्तर गलत हैं।

देख:

https://restfulapi.net/rest-api-design-tutorial-with-example/

https://restfulapi.net/rest-put-vs-post/

https://restfulapi.net/http-methods/#patch

डाल

मौजूदा संसाधन को अपडेट करने के लिए मुख्य रूप से PUT API का उपयोग करें (यदि संसाधन मौजूद नहीं है, तो API एक नया संसाधन बनाने का निर्णय ले सकता है या नहीं)। यदि PUT API द्वारा एक नया संसाधन बनाया गया है, तो मूल सर्वर HTTP एजेंट को HTTP प्रतिसाद कोड 201 (निर्मित) प्रतिक्रिया के माध्यम से सूचित करता है और यदि कोई मौजूदा संसाधन संशोधित किया जाता है, तो 200 (ठीक) या 204 (कोई सामग्री नहीं) अनुरोध के सफल समापन को इंगित करने के लिए प्रतिक्रिया कोड भेजे जाने चाहिए।

यदि अनुरोध कैश से गुजरता है और अनुरोध-यूआरआई एक या अधिक वर्तमान में कैश्ड संस्थाओं की पहचान करता है, तो उन प्रविष्टियों को बासी माना जाएगा। इस पद्धति के लिए जवाबदेही उपलब्ध नहीं हैं।

PUT का उपयोग तब करें जब आप एक विलक्षण संसाधन को संशोधित करना चाहते हैं जो पहले से ही संसाधन संग्रह का एक हिस्सा है। PUT संसाधन को पूरी तरह से बदल देता है। यदि संसाधन के अद्यतन भाग का अनुरोध करें तो PATCH का उपयोग करें।

PATCH

HTTP पाच अनुरोध एक संसाधन पर आंशिक अद्यतन करने के लिए है। यदि आप PUT अनुरोधों को देखते हैं तो एक संसाधन इकाई को और अधिक स्पष्ट करने के लिए संशोधित करें - PATCH विधि आंशिक रूप से किसी मौजूदा संसाधन को अपडेट करने के लिए सही विकल्प है और PUT का उपयोग केवल तभी किया जाना चाहिए जब आप इसकी संपूर्णता में एक संसाधन की जगह ले रहे हों।

तो आपको इसे इस तरह से उपयोग करना चाहिए:

POST    /device-management/devices      : Create a new device
PUT     /device-management/devices/{id} : Update the device information identified by "id"
PATCH   /device-management/devices/{id} : Partial-update the device information identified by "id"

उत्साहपूर्ण प्रथाओं से संकेत मिलता है कि इससे कोई फर्क नहीं पड़ता कि आप PUT / {id} पर क्या करते हैं - रिकॉर्ड की सामग्री को पेलोड द्वारा प्रदान किए गए अपडेट में अपडेट किया जाना चाहिए - लेकिन GET / {id} अभी भी उसी संसाधन से लिंक होना चाहिए।

दूसरे शब्दों में, PUT / 3 4 को पेलोड आईडी में अपडेट कर सकता है, लेकिन GET / 3 को अभी भी उसी पेलोड से लिंक करना चाहिए (और आईडी सेट के साथ एक को 4 पर लौटाएं)।

यदि आप यह तय कर रहे हैं कि आपके एपीआई को यूआरआई और पेलोड में समान पहचानकर्ता की आवश्यकता है, तो यह सुनिश्चित करना आपका काम है कि यह मेल खाता है, लेकिन PUT के बजाय PATCH का उपयोग जरूर करें यदि आप उस पेलोड में आईडी को बाहर कर रहे हैं जो उसकी संपूर्णता में होना चाहिए । यहीं पर स्वीकृत उत्तर गलत मिला। PUT को पूरे संसाधन को बदलना होगा, जहाँ-जैसे पैच आंशिक हो सकता है।


2

हालांकि, विभिन्न कार्यों के लिए अलग-अलग अभ्यावेदन करना ठीक है, लेकिन PUT के लिए एक सामान्य अनुशंसा WHOLE पेलोड को समाहित करना है । इसका मतलब है कि idवहाँ भी होना चाहिए। अन्यथा, आपको PATCH का उपयोग करना चाहिए।

यह कहने के बाद कि, मुझे लगता है कि PUT को ज्यादातर अपडेट के लिए उपयोग किया idजाना चाहिए और हमेशा URL में भी पास होना चाहिए। इसके परिणामस्वरूप, संसाधन पहचानकर्ता को अपडेट करने के लिए PUT का उपयोग करना एक बुरा विचार है। यह हमें एक अवांछनीय स्थिति में छोड़ देता है जब idURL idशरीर में अलग हो सकता है।

तो, हम इस तरह के संघर्ष को कैसे हल करते हैं? हमारे पास मूल रूप से 2 विकल्प हैं:

  • एक 4XX अपवाद फेंकें
  • एक Warning( X-API-Warnआदि) शीर्ष लेख जोड़ें ।

इस प्रश्न का उत्तर देने के लिए मैं जितना करीब हो सकता हूं, क्योंकि सामान्य रूप से विषय एक राय का विषय है।


1

विभिन्न दृष्टिकोणों का उपयोग करने में कुछ भी बुरा नहीं है। लेकिन मुझे लगता है कि सबसे अच्छा तरीका 2 के साथ समाधान है ।

 PUT /person/UUID {"name": "Jimmy"}

 GET /person/UUID returns {"id": <UUID>, "name": "Jimmy"}

इसका उपयोग ज्यादातर इस तरह से किया जाता है, यहां तक ​​कि इकाई ढांचा भी इस तकनीक का उपयोग करता है जब इकाई को dbContext में जोड़ा जाता है बिना उत्पन्न आईडी के वर्ग एंटिटी फ्रेमवर्क में संदर्भ द्वारा उत्पन्न आईडी है।


1

मैं इसे JSON-LD / अर्थ वेब के नज़रिए से देख रहा हूं क्योंकि यह वास्तविक REST अनुरूपता प्राप्त करने के लिए एक अच्छा तरीका है जैसा कि मैंने इन स्लाइड्स में बताया है । इसे उस दृष्टिकोण से देखते हुए, विकल्प के लिए जाने का कोई प्रश्न नहीं है (1.) क्योंकि वेब संसाधन की आईडी (IRI) हमेशा उस URL के बराबर होनी चाहिए जिसका उपयोग मैं संसाधन को देखने / अपग्रेड करने के लिए कर सकता हूं। मुझे लगता है कि सत्यापन को लागू करना वास्तव में कठिन नहीं है और न ही यह कम्प्यूटेशनल रूप से तीव्र है; इसलिए मैं विकल्प (2.) के साथ जाने के लिए इसे वैध कारण नहीं मानता। मुझे लगता है कि विकल्प (3.) वास्तव में एक विकल्प नहीं है क्योंकि POST (नया बनाएं) में PUT (अपडेट / बदलें) की तुलना में एक अलग शब्दार्थ है।


0

आपको PATCH / PUT अनुरोध प्रकार देखने पड़ सकते हैं।

PATCH अनुरोधों का उपयोग आंशिक रूप से एक संसाधन को अपडेट करने के लिए किया जाता है जबकि PUT अनुरोधों में, आपको पूरे संसाधन को भेजना होगा जहां यह सर्वर पर ओवरराइड हो जाता है।

जहाँ तक url में ID होने का सवाल है, मुझे लगता है कि आपके पास हमेशा होना चाहिए क्योंकि किसी संसाधन की पहचान करने के लिए यह एक मानक अभ्यास है। यहां तक ​​कि स्ट्राइप एपीआई भी इस तरह से काम करता है।

आप पहचान करने के लिए आईडी के साथ सर्वर पर एक संसाधन को अपडेट करने के लिए एक पाच अनुरोध का उपयोग कर सकते हैं लेकिन वास्तविक आईडी को अपडेट नहीं करते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.