क्या मुझे अपने REST API में PATCH या PUT का उपयोग करना चाहिए?


274

मैं निम्नलिखित परिदृश्य के लिए उपयुक्त विधि के साथ अपने बाकी समापन बिंदु को डिजाइन करना चाहता हूं।

एक समूह है। प्रत्येक समूह की एक स्थिति है। समूह को व्यवस्थापक द्वारा सक्रिय या निष्क्रिय किया जा सकता है।

क्या मुझे अपना अंतिम बिंदु डिजाइन करना चाहिए?

PUT /groups/api/v1/groups/{group id}/status/activate

या

PATCH /groups/api/v1/groups/{group id}

with request body like 
{action:activate|deactivate}

1
दोनों ठीक हैं। लेकिन JSON PATCH फॉर्मेट ( tools.ietf.org/html/rfc6902 ) के लिए RFC पर एक नज़र डालें । PATCH को पेलोड (और कच्चा JSON उनमें से एक नहीं है) के लिए किसी प्रकार का भिन्न / पैच दस्तावेज़ प्राप्त करने की उम्मीद है।
जॉर्न वाइल्ड

1
@ JørnWildt नहीं, PUT एक भयानक विकल्प होगा। तुम वहाँ क्या लगा रहे हो? PATCH एकमात्र समझदार विकल्प है। ठीक है, इस मामले में आप प्रश्न में प्रस्तुत PATCH प्रारूप का उपयोग कर सकते हैं, और बस PUT विधि का उपयोग कर सकते हैं; PUT उदाहरण सिर्फ गलत है।
thecoshman

3
एक या एक से अधिक गुणों को स्टैंडअलोन संसाधनों के रूप में उजागर करने में कुछ भी गलत नहीं है जो एक ग्राहक PUT के साथ प्राप्त और संशोधित कर सकता है। लेकिन, हाँ, URL तब होना चाहिए / समूह / एपीआई / v1 / समूह / {समूह आईडी} / स्थिति जिसे आप "सक्रिय" या "निष्क्रिय" या वर्तमान स्थिति को पढ़ने के लिए प्राप्त कर सकते हैं।
जोर्न वाइल्ड

3
यहां तरीका देखें: PATCH वास्तव में इस्तेमाल किया जाना चाहिए का एक अच्छा व्याख्या दी गई है williamdurand.fr/2014/02/14/please-do-not-patch-like-an-idiot
Rishat

4
" activate" पर्याप्त RESTful निर्माण नहीं है। आप शायद status"सक्रिय" या "निष्क्रिय" को अपडेट करने की कोशिश कर रहे हैं । जिस स्थिति में आप .../statusशरीर में "सक्रिय" या "निष्क्रिय" स्ट्रिंग के साथ पाट सकते हैं । या यदि आप एक बूलियन को अद्यतन करने की कोशिश कर रहे हैं status.active, तो आप .../status/activeशरीर में बूलियन के साथ पाच कर सकते हैं
ऑगियो गार्डनर

जवाबों:


328

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

आंशिक संसाधन संशोधन के बारे में अधिक जानकारी RFC 5789 में उपलब्ध है । विशेष रूप से, PUTविधि इस प्रकार वर्णित है:

हाइपरटेक्स्ट ट्रांसफर प्रोटोकॉल (HTTP) का विस्तार करने वाले कई अनुप्रयोगों को आंशिक संसाधन संशोधन करने के लिए एक सुविधा की आवश्यकता होती है। मौजूदा HTTP PUT विधि केवल एक दस्तावेज़ के पूर्ण प्रतिस्थापन की अनुमति देती है। यह प्रस्ताव एक मौजूदा HTTP संसाधन को संशोधित करने के लिए एक नया HTTP विधि, PATCH जोड़ता है।


1
निष्पक्ष होने के लिए, आप स्ट्रिंग को 'सक्रिय' कर सकते हैं या संसाधन को निष्क्रिय कर सकते हैं। जैसा कि लगता है (केवल) टॉगल करने के लिए एक ही चीज़ है, पूरी तरह से इसे बदलना इतना बड़ा सौदा नहीं है। और यह एक छोटे से अनुरोध के लिए अनुमति देता है।
Thecoshman

35
यह ध्यान रखना महत्वपूर्ण है कि RFC 5789 अभी भी प्रस्ताव के चरण में है और आधिकारिक तौर पर स्वीकार नहीं किया गया है और वर्तमान में इसे 'इरेटा अस्तित्व' के रूप में चिह्नित किया गया है। यह 'सर्वोत्तम अभ्यास' अत्यधिक बहस का है और तकनीकी रूप से PATCH अभी तक HTTP मानक का हिस्सा नहीं है।
फिशपेन0

4
बस कुछ साल बाद मेरे 2 सेंट: आप स्थिति को स्वयं एक संसाधन मान सकते हैं, और यदि ऐसा है, तो PUT के खिलाफ / स्थिति का उपयोग करना तकनीकी रूप से उस अंतिम बिंदु पर स्थिति संसाधन की जगह लेगा।
जोनो स्टीवर्ट

3
मैं डॉक्स के खिलाफ बहस करने की हिम्मत करूंगा, भले ही यह "आरएफसी" हो। डॉक्स का कहना है कि आपको किसी संसाधन के एक हिस्से को संशोधित करने के लिए PATCH का उपयोग करना चाहिए, लेकिन इसने महत्वपूर्ण बात को छोड़ दिया कि PATCH विधि को एक गैर-बेरोजगार विधि के रूप में परिभाषित किया गया है। क्यों? यदि PUT विधि को संपूर्ण संसाधन के अद्यतन / प्रतिस्थापन को ध्यान में रखते हुए बनाया गया था, तो PUTCH पद्धति को PUT जैसी एक सुस्पष्ट विधि के रूप में क्यों नहीं बनाया गया, यदि इसका उद्देश्य केवल संसाधन के भाग को अद्यतन करना था? मेरे लिए, यह अपडेट की idempotency में अधिक अंतर दिखता है, जैसे "a = 5" (PUT) और "a = a + 5" (PATCH)। दोनों पूरे संसाधन को अपडेट कर सकते हैं।
म्लादेन बी।

179

आर बाकी हिस्सों में संसाधन के लिए खड़ा है

(यह सच नहीं है, क्योंकि यह प्रतिनिधि के लिए खड़ा है, लेकिन यह REST में संसाधनों के महत्व को याद रखने के लिए एक अच्छी चाल है)।

के बारे में PUT /groups/api/v1/groups/{group id}/status/activate: आप "सक्रिय" अपडेट नहीं कर रहे हैं । एक "सक्रिय" एक चीज नहीं है, यह एक क्रिया है। क्रिया कभी अच्छे संसाधन नहीं होते हैं। अंगूठे का एक नियम: यदि क्रिया, क्रिया, URL में है, तो यह संभवतः RESTful नहीं है

आप इसके बजाय क्या कर रहे हैं? या तो आप किसी समूह पर "जोड़ना", "हटाना" या " सक्रिय करना" सक्रिय कर रहे हैं, या यदि आप चाहें तो: किसी समूह पर "स्थिति" -resource में हेरफेर कर रहे हैं। व्यक्तिगत रूप से, मैं "सक्रियण" का उपयोग करूंगा क्योंकि वे अवधारणा "स्थिति" से कम अस्पष्ट हैं: स्थिति बनाना अस्पष्ट है, सक्रियण बनाना नहीं है।

  • POST /groups/{group id}/activation सक्रियण बनाता है (या निर्माण का अनुरोध करता है)।
  • PATCH /groups/{group id}/activationकिसी मौजूदा सक्रियण के कुछ विवरण अपडेट करता है। चूंकि एक समूह में केवल एक ही सक्रियण होता है, हम जानते हैं कि हम किस सक्रियता-संसाधन का उल्लेख कर रहे हैं।
  • PUT /groups/{group id}/activationपुरानी सक्रियता को सम्मिलित करता है या प्रतिस्थापित करता है। चूंकि एक समूह में केवल एक ही सक्रियण होता है, हम जानते हैं कि हम किस सक्रियता-संसाधन का उल्लेख कर रहे हैं।
  • DELETE /groups/{group id}/activation सक्रियण को रद्द या हटा देगा।

यह पैटर्न तब उपयोगी होता है जब किसी समूह के "सक्रियण" के दुष्प्रभाव होते हैं, जैसे भुगतान किए जा रहे हैं, मेल भेजे जा रहे हैं और इसी तरह। केवल POST और PATCH के ऐसे दुष्प्रभाव हो सकते हैं। जब उदाहरण के लिए एक सक्रियण को हटाने की आवश्यकता होती है, तो उपयोगकर्ताओं को मेल पर सूचित करें, DELETE सही विकल्प नहीं है; उस मामले में आप शायद करना चाहते हैं एक छोड़ना संसाधन बना : POST /groups/{group_id}/deactivation

इन दिशानिर्देशों का पालन करना एक अच्छा विचार है, क्योंकि यह मानक अनुबंध आपके ग्राहकों के लिए बहुत स्पष्ट करता है, और ग्राहक और आपके बीच की सभी प्रॉक्सी और परतें जानती हैं कि यह कब सुरक्षित है, और कब नहीं। मान लें कि क्लाइंट कहीं फ्लैकी वाईफाई के साथ है, और उसका उपयोगकर्ता "निष्क्रिय" पर क्लिक करता है, जो कि ट्रिगर करता है DELETE: यदि वह विफल रहता है, तो ग्राहक बस 404, 200 या कुछ और जब तक इसे संभाल सकता है, तब तक पुन: प्रयास कर सकता है। लेकिन अगर यह ट्रिगर करता है तो POST to deactivationयह पता नहीं है कि फिर से प्रयास न करें: POST इसका अर्थ है।
अब किसी भी क्लाइंट के पास एक अनुबंध है, जिसका पालन करने पर, "आपके समूह को निष्क्रिय कर दिया गया है" 42 ईमेल भेजने से रक्षा करेगा, केवल इसलिए कि इसका HTTP- पुस्तकालय बैकएंड पर कॉल को पुनः प्राप्त करता रहा।

एकल विशेषता को अद्यतन करना: PATCH का उपयोग करें

PATCH /groups/{group id}

मामले में आप एक विशेषता को अद्यतन करना चाहते हैं। उदाहरण के लिए "स्थिति" समूह पर एक विशेषता हो सकती है जिसे सेट किया जा सकता है। "स्टेटस" जैसी एक विशेषता अक्सर मूल्यों के श्वेतसूची में सीमित करने के लिए एक अच्छा उम्मीदवार है। कुछ अपरिभाषित JSON-योजना के उदाहरणों का उपयोग करें:

PATCH /groups/{group id} { "attributes": { "status": "active" } }
response: 200 OK

PATCH /groups/{group id} { "attributes": { "status": "deleted" } }
response: 406 Not Acceptable

संसाधन की जगह, साइड-इफेक्ट्स के बिना PUT का उपयोग करें।

PUT /groups/{group id}

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

ग्राहक को PUTअनुरोध के मामले में , हमेशा पूरे संसाधन भेजना चाहिए, एक नया आइटम बनाने के लिए आवश्यक सभी डेटा: आमतौर पर POST-create के समान डेटा की आवश्यकता होगी।

PUT /groups/{group id} { "attributes": { "status": "active" } }
response: 406 Not Acceptable

PUT /groups/{group id} { "attributes": { "name": .... etc. "status": "active" } }
response: 201 Created or 200 OK, depending on whether we made a new one.

एक बहुत ही महत्वपूर्ण आवश्यकता यह है कि PUTयह एक आदर्श है : यदि आपको समूह को अपडेट करते समय साइड-इफेक्ट्स की आवश्यकता होती है (या सक्रियण बदलते हुए), तो आपको उपयोग करना चाहिए PATCH। इसलिए, जब अपडेट मेल में भेजते हैं, तो उपयोग न करें PUT


3
यह मेरे लिए बहुत जानकारीपूर्ण था। "यह पैटर्न तब उपयोगी होता है जब किसी समूह के" सक्रियण "के साइड-इफेक्ट्स होते हैं" - यह पैटर्न कैसे उपयोगी है, विशेष रूप से तब होता है जब क्रियाओं के साइड इफेक्ट्स होते हैं, जैसा कि ओपी प्रारंभिक समापन बिंदुओं के विपरीत है
अब्दुल

1
@ अब्दुल, पैटर्न बहुत सारे कारणों से उपयोगी है, लेकिन wrt दुष्परिणाम, यह एक ग्राहक के लिए बहुत स्पष्ट होना चाहिए, क्या प्रभाव पड़ता है। जब, कहते हैं, एक आईओएस ऐप पूरी एड्रेसबुक को "कॉन्टैक्ट्स" के रूप में भेजने का फैसला करता है, तो यह बेहद स्पष्ट होना चाहिए कि किसी कॉन्टैक्ट का क्रिएट, अपडेट, डिलीट आदि क्या साइड-इफेक्ट करता है। उदाहरण के लिए, सभी संपर्कों को मास-मेलिंग से बचने के लिए।
Berkes

1
RESTfull PUT में इकाइयां भी बदल सकती हैं पहचान - उदाहरण के लिए PrimaryKey ID जहां यह एक समानांतर अनुरोध को विफल करने का कारण बन सकता है। (उदाहरण के लिए पूरी इकाई को अपडेट करने के लिए कुछ पंक्तियों को हटाने और नए जोड़ने की आवश्यकता होती है, इसलिए नई इकाइयाँ बनाना) जहां PATCH को ऐसा करने में सक्षम नहीं होना चाहिए, अन्य "एप्लिकेशन" को प्रभावित किए बिना असीमित संख्या में पाच अनुरोधों की अनुमति देना
Piotr Kula

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

1
@richremer सेवाएं, मॉडल की तरह, आंतरिक सार हैं। जिस तरह REST-समापन बिंदुओं-और-ORM- मॉडल या यहां तक ​​कि डेटाबेस तालिकाओं के बीच 1-1 संबंध की आवश्यकता के लिए यह एक खराब अमूर्तता है, सेवाओं को उजागर करना खराब अमूर्तता है। आपके API के बाहर, डोमेन मॉडल से संवाद करना चाहिए। आप उन्हें आंतरिक रूप से कैसे लागू करते हैं, इसका एपीआई से कोई सरोकार नहीं है। अपने API को बदले बिना आपको एक्टिवेशन सर्विस से CQRS आधारित एक्टिवेशन फ्लो में जाने के लिए स्वतंत्र होना चाहिए।
16

12

मैं PATCH का उपयोग करने की सलाह दूंगा, क्योंकि आपके संसाधन 'समूह' में कई गुण हैं लेकिन इस मामले में, आप केवल सक्रियण क्षेत्र (आंशिक संशोधन) को अपडेट कर रहे हैं

RFC5789 ( https://tools.ietf.org/html/rfc5789 ) के अनुसार

मौजूदा HTTP PUT विधि केवल एक दस्तावेज़ के पूर्ण प्रतिस्थापन की अनुमति देती है। यह प्रस्ताव एक मौजूदा HTTP संसाधन को संशोधित करने के लिए एक नया HTTP विधि, PATCH जोड़ता है।

इसके अलावा, अधिक विवरण में,

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

PATCH के आवेदन द्वारा संशोधित या मौजूदा बनाए जा सकते हैं ।

[RFC2616], खंड 9.1 द्वारा परिभाषित के अनुसार PATCH न तो सुरक्षित है और न ही बेकार है।

ग्राहकों को PUT के बजाय PATCH का उपयोग करते समय चुनना होगा। उदाहरण के
लिए, यदि पैच दस्तावेज़ का आकार
PUT में उपयोग किए जाने वाले नए संसाधन डेटा के आकार से बड़ा है , तो
PATCH के बजाय PUT का उपयोग करने का अर्थ हो सकता है । POST की तुलना और भी कठिन है, क्योंकि POST का उपयोग व्यापक रूप से भिन्न तरीकों से किया जाता है और
यदि सर्वर चुनता है तो PUT और PATCH जैसे संचालन को सम्मिलित कर सकता है। यदि
ऑपरेशन अनुरोध-यूआरआई द्वारा पहचाने गए संसाधन को अनुमानित रूप से संशोधित नहीं करता है, तो PATCH
या PUT के बजाय POST पर विचार किया जाना चाहिए ।

PATCH के लिए प्रतिक्रिया कोड है

204 रिस्पांस कोड का उपयोग किया जाता है क्योंकि रिस्पांस एक संदेश निकाय नहीं ले जाता है (जो 200 कोड के साथ प्रतिक्रिया होती है)। ध्यान दें कि अन्य सफलता कोड भी इस्तेमाल किए जा सकते हैं।

थ्रेटप भी देखें: //restcookbook.com/HTTP%20Methods/patch/

कैविएट: एक एपीआई जो पैट को लागू कर रहा है उसे परमाणु रूप से पैच करना चाहिए। यह संभव नहीं होगा कि GET द्वारा अनुरोध किए जाने पर संसाधन आधे-अधूरे हों।


7

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

/groups/api/groups/{group id}/status

संशोधन के लिए PATCH पर इस दृष्टिकोण का नकारात्मक पक्ष यह है कि आप एक समूह की एक से अधिक संपत्ति पर एटोमिक और ट्रांजैक्शनल रूप से बदलाव नहीं कर पाएंगे। यदि लेन-देन परिवर्तन महत्वपूर्ण हैं तो PATCH का उपयोग करें।

यदि आप समूह के उप-संसाधन के रूप में स्थिति को उजागर करने का निर्णय लेते हैं तो यह समूह के प्रतिनिधित्व में एक कड़ी होनी चाहिए। उदाहरण के लिए यदि एजेंट को समूह 123 मिलता है और एक्सएमएल स्वीकार करता है तो प्रतिक्रिया निकाय में हो सकती है:

<group id="123">
  <status>Active</status>
  <link rel="/linkrels/groups/status" uri="/groups/api/groups/123/status"/>
  ...
</group>

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


0

मैं आम तौर पर कुछ सरल करना पसंद करूंगा, जैसे activate/ deactivateउप-संसाधन ( Linkहेडर के साथ जुड़ा हुआ rel=service)।

POST /groups/api/v1/groups/{group id}/activate

या

POST /groups/api/v1/groups/{group id}/deactivate

उपभोक्ता के लिए, यह इंटरफ़ेस मृत-सरल है, और यह व्यक्तिगत संसाधनों के रूप में "सक्रियण" की अवधारणा में आपको पीछे किए बिना अन्य सिद्धांतों का पालन करता है।


0

इस तरह के व्यवहार को लागू करने का एक संभावित विकल्प है

PUT /groups/api/v1/groups/{group id}/status
{
    "Status":"Activated"
}

और जाहिर है, अगर किसी को इसे निष्क्रिय करने की आवश्यकता है, PUTतो DeactivatedJSON में स्थिति होगी ।

सामूहिक सक्रियण / निष्क्रियता की आवश्यकता के मामले PATCHमें, खेल में कदम रख सकते हैं (सटीक समूह के लिए नहीं, बल्कि groupsसंसाधन के लिए:

PATCH /groups/api/v1/groups
{
    { “op”: “replace”, “path”: “/group1/status”, “value”: “Activated” },
    { “op”: “replace”, “path”: “/group7/status”, “value”: “Activated” },
    { “op”: “replace”, “path”: “/group9/status”, “value”: “Deactivated” }
}

सामान्य तौर पर यह विचार @Andrew Dobrowolski का सुझाव है, लेकिन सटीक अहसास में थोड़े बदलाव के साथ।

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