REST API वास्तविक जीवन परिदृश्यों में PUTCH PATCH विधियों का उपयोग करें


681

सबसे पहले, कुछ परिभाषाएँ:

PUT को धारा 9.6 RFC 2616 में परिभाषित किया गया है :

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

PATCH को RFC 5789 में परिभाषित किया गया है :

PATCH विधि अनुरोध करती है कि अनुरोध इकाई में वर्णित परिवर्तनों का एक सेट अनुरोध- URI द्वारा पहचाने गए संसाधन पर लागू हो।

इसके अलावा RFC 2616 धारा 9.1.2 PUT के अनुसार बेरोजगार है जबकि PATCH नहीं है।

अब एक वास्तविक उदाहरण पर एक नज़र डालते हैं। जब मैं /usersडेटा के साथ POST करता हूं {username: 'skwee357', email: 'skwee357@domain.com'}और सर्वर एक संसाधन बनाने में सक्षम होता है, तो यह 201 और संसाधन स्थान के साथ प्रतिक्रिया देगा (मान लेता है /users/1) और GET पर कोई भी अगली कॉल /users/1वापस आ जाएगी {id: 1, username: 'skwee357', email: 'skwee357@domain.com'}

अब हम कहते हैं कि मैं अपना ईमेल संशोधित करना चाहता हूँ। ईमेल संशोधन को "परिवर्तनों का एक सेट" माना जाता है और इसलिए मुझे /users/1" पैच दस्तावेज़ " के साथ पैट चाहिए । मेरे मामले में यह json दस्तावेज़ होगा {email: 'skwee357@newdomain.com'}:। सर्वर फिर 200 लौटाता है (मान लेना ठीक है)। यह मुझे पहले सवाल पर लाता है:

  • पथ बेकार नहीं है। RFC 2616 और RFC 5789 में ऐसा कहा गया है। हालाँकि अगर मैं उसी PATCH अनुरोध (अपने नए ईमेल के साथ) को जारी करता हूं, तो मुझे वही संसाधन स्थिति मिलेगी (मेरे ईमेल को अनुरोधित मूल्य में संशोधित किया जाएगा)। PATCH तब क्यों नहीं है बेरोजगार?

PATCH एक अपेक्षाकृत नई क्रिया है (RFC मार्च 2010 में शुरू की गई), और यह "पैचिंग" या खेतों के एक सेट को संशोधित करने की समस्या को हल करने के लिए आती है। PATCH शुरू होने से पहले, हर कोई संसाधनों को अपडेट करने के लिए PUT का उपयोग करता था। लेकिन PATCH के आने के बाद, यह मुझे उलझन में छोड़ देता है कि PUT का उपयोग किस लिए किया जाता है। और यह मुझे मेरे दूसरे (और मुख्य) प्रश्न पर लाता है:

  • PUT और PATCH के बीच वास्तविक अंतर क्या है? मैंने कहीं पढ़ा है कि PUT का उपयोग विशिष्ट संसाधन के तहत पूरी इकाई को बदलने के लिए किया जा सकता है , इसलिए किसी को पूर्ण इकाई (बजाय PATCH के साथ विशेषताओं के सेट के बजाय) को भेजना चाहिए। ऐसे मामले के लिए वास्तविक व्यावहारिक उपयोग क्या है? आप किसी विशिष्ट संसाधन URI में किसी इकाई को कब बदलना / अधिलेखित करना चाहेंगे और इस तरह के एक ऑपरेशन को इकाई को अपडेट / पैचिंग क्यों नहीं माना जाता है? एकमात्र व्यावहारिक उपयोग केस जिसे मैं PUT के लिए देखता हूं, एक संग्रह पर PUT जारी कर रहा है, यानी /usersपूरे संग्रह को बदलने के लिए। एक विशिष्ट इकाई पर PUT जारी करना PATCH शुरू होने के बाद कोई मतलब नहीं है। क्या मै गलत हु?

1
a) यह RFC 2616 है, 2612 नहीं है। b) RFC 2616 का पालन किया गया है, PUT का वर्तमान अनुमान ग्रीनबाइट्स में है। / / / / bbdav / rfc7231.html# PUT , c) मुझे आपका प्रश्न नहीं मिला; यह बिल्कुल स्पष्ट नहीं है कि PUTCH को पेश किए जाने से पहले PUT का उपयोग किसी भी संसाधन को करने के लिए किया जा सकता है, न केवल एक संग्रह, d), लोग आमतौर पर POST, e) का उपयोग करते थे, हां, एक विशिष्ट PATCH अनुरोध (पैच प्रारूप के आधार पर) उदासीन हो सकता है; यह सिर्फ इतना है कि यह आम तौर पर नहीं है।
जूलियन रेश्के

अगर यह मदद करता है मैं PATCH बनाम PUT पर एक लेख लिखा था गए eq8.eu/blogs/36-patch-vs-put-and-the-patch-json-syntax-war
equivalent8

5
सरल: POST एक संग्रह में एक आइटम बनाता है। PUT एक आइटम को प्रतिस्थापित करता है। PATCH एक आइटम को संशोधित करता है। जब पोस्टिंग होती है, तो नए आइटम के लिए URL की गणना की जाती है और प्रतिक्रिया में वापस किया जाता है, जबकि PUT और PATCH को अनुरोध में URL की आवश्यकता होती है। सही?
टॉम रसेल

यह पोस्ट उपयोगी हो सकती है: POST vs PUT vs PATCH: mscharhag.com/api-design/http-post-put-patch
micha

जवाबों:


943

नोट : जब मैंने पहली बार REST के बारे में पढ़ते हुए समय बिताया, तो idempotence सही होने की कोशिश करने के लिए एक भ्रामक अवधारणा थी। मुझे अभी भी अपने मूल उत्तर में यह ठीक नहीं लगा, जैसा कि आगे की टिप्पणी (और जेसन होएगर के उत्तर ) ने दिखाया है। थोड़ी देर के लिए, मैंने इस उत्तर को बड़े पैमाने पर अपडेट करने का विरोध किया है, जेसन को प्रभावी ढंग से रोकने के लिए, लेकिन मैं इसे अब संपादित कर रहा हूं क्योंकि, ठीक है, मुझे (टिप्पणियों में) पूछा गया था।

मेरे उत्तर को पढ़ने के बाद, मेरा सुझाव है कि आप इस प्रश्न का जेसन होइटर का उत्कृष्ट उत्तर भी पढ़ें , और मैं केवल जेसन से चोरी किए बिना अपने उत्तर को बेहतर बनाने का प्रयास करूंगा।

क्यों है PUT सुस्पष्ट?

जैसा कि आपने अपने RFC 2616 प्रशस्ति पत्र में उल्लेख किया है, PUT को बेरोजगार माना जाता है। जब आप किसी संसाधन को प्राप्त करते हैं, तो ये दो धारणाएं खेल में होती हैं:

  1. आप एक इकाई की बात कर रहे हैं, किसी संग्रह की नहीं।

  2. आपके द्वारा आपूर्ति की जाने वाली इकाई पूर्ण ( संपूर्ण इकाई) है।

आइए आपके एक उदाहरण को देखें।

{ "username": "skwee357", "email": "skwee357@domain.com" }

यदि आप इस दस्तावेज़ को पोस्ट करते हैं /users , जैसा कि आप सुझाव देते हैं, तो आप इस तरह के रूप में एक इकाई वापस पा सकते हैं

## /users/1

{
    "username": "skwee357",
    "email": "skwee357@domain.com"
}

यदि आप इस इकाई को बाद में संशोधित करना चाहते हैं, तो आप PUT और PATCH के बीच चयन करें। एक PUT इस तरह दिख सकता है:

PUT /users/1
{
    "username": "skwee357",
    "email": "skwee357@gmail.com"       // new email address
}

आप पाच का उपयोग करके इसे पूरा कर सकते हैं। यह इस तरह लग सकता है:

PATCH /users/1
{
    "email": "skwee357@gmail.com"       // new email address
}

आपको इन दोनों के बीच अंतर दिखाई देगा। PUT में इस उपयोगकर्ता के सभी पैरामीटर शामिल थे, लेकिन PATCH में केवल वही शामिल था जिसे संशोधित किया जा रहा था ( email)।

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

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

PUT का गलत उपयोग करना

यदि आप एक PUT अनुरोध में उपरोक्त PATCH डेटा का उपयोग करते हैं तो क्या होगा?

GET /users/1
{
    "username": "skwee357",
    "email": "skwee357@domain.com"
}
PUT /users/1
{
    "email": "skwee357@gmail.com"       // new email address
}

GET /users/1
{
    "email": "skwee357@gmail.com"      // new email address... and nothing else!
}

(मैं इस सवाल के प्रयोजनों के लिए मान रहा हूं कि सर्वर के पास कोई विशिष्ट आवश्यक फ़ील्ड नहीं है, और ऐसा करने की अनुमति देगा ... जो वास्तव में ऐसा नहीं हो सकता है।)

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

उदाहरण के लिए यहाँ उदाहरण है - वास्तव में ऐसा कभी मत करो। यह PUT अनुरोध तकनीकी रूप से उदासीन है, लेकिन इसका मतलब यह नहीं है कि यह एक भयानक, टूटा हुआ विचार नहीं है।

PATCH को कैसे बनाया जा सकता है?

उपर्युक्त उदाहरण में, PATCH आलसी था । आपने एक परिवर्तन किया, लेकिन यदि आपने बार-बार एक ही परिवर्तन किया, तो यह हमेशा एक ही परिणाम देगा: आपने ईमेल पते को नए मूल्य में बदल दिया।

GET /users/1
{
    "username": "skwee357",
    "email": "skwee357@domain.com"
}
PATCH /users/1
{
    "email": "skwee357@gmail.com"       // new email address
}

GET /users/1
{
    "username": "skwee357",
    "email": "skwee357@gmail.com"       // email address was changed
}
PATCH /users/1
{
    "email": "skwee357@gmail.com"       // new email address... again
}

GET /users/1
{
    "username": "skwee357",
    "email": "skwee357@gmail.com"       // nothing changed since last GET
}

मेरा मूल उदाहरण, सटीकता के लिए तय किया गया

मेरे पास मूल रूप से ऐसे उदाहरण थे जो मुझे लगा कि गैर-बेरोजगारी दिखा रहे हैं, लेकिन वे भ्रामक / गलत थे। मैं उदाहरणों को रखने जा रहा हूं, लेकिन एक अलग चीज को चित्रित करने के लिए उनका उपयोग कर रहा हूं: एक ही इकाई के खिलाफ कई PATCH दस्तावेज, विभिन्न विशेषताओं को संशोधित करते हुए, PATCHes को गैर-बेरोजगार नहीं बनाते हैं।

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

{
  "id": 1,
  "name": "Sam Kwee",
  "email": "skwee357@olddomain.com",
  "address": "123 Mockingbird Lane",
  "city": "New York",
  "state": "NY",
  "zip": "10001"
}

एक पैट के बाद, आपके पास एक संशोधित इकाई है:

PATCH /users/1
{"email": "skwee357@newdomain.com"}

{
  "id": 1,
  "name": "Sam Kwee",
  "email": "skwee357@newdomain.com",    // the email changed, yay!
  "address": "123 Mockingbird Lane",
  "city": "New York",
  "state": "NY",
  "zip": "10001"
}

यदि आप अपने पैट को बार-बार लागू करते हैं, तो आपको एक ही परिणाम प्राप्त होता रहेगा: ईमेल को नए मूल्य में बदल दिया गया था। A अंदर जाता है, A बाहर आता है, इसलिए यह एक आदर्श है।

एक घंटे बाद, जब आप कुछ कॉफी बनाने और विराम लेने के लिए गए थे, तो कोई और व्यक्ति अपने पैट के साथ आता है। ऐसा लगता है कि डाकघर कुछ बदलाव कर रहा है।

PATCH /users/1
{"zip": "12345"}

{
  "id": 1,
  "name": "Sam Kwee",
  "email": "skwee357@newdomain.com",  // still the new email you set
  "address": "123 Mockingbird Lane",
  "city": "New York",
  "state": "NY",
  "zip": "12345"                      // and this change as well
}

चूँकि पोस्ट ऑफिस का यह PATCH खुद को ईमेल से चिंतित नहीं करता है, केवल ज़िप कोड है, यदि इसे बार-बार लागू किया जाता है, तो इसे भी वही परिणाम मिलेगा: ज़िप कोड नए मूल्य पर सेट होता है। A अंदर जाता है, A बाहर आता है, इसलिए यह भी बेकार है।

अगले दिन, आप अपने पैट को फिर से भेजने का फैसला करते हैं।

PATCH /users/1
{"email": "skwee357@newdomain.com"}

{
  "id": 1,
  "name": "Sam Kwee",
  "email": "skwee357@newdomain.com",
  "address": "123 Mockingbird Lane",
  "city": "New York",
  "state": "NY",
  "zip": "12345"
}

आपके पैच का वही प्रभाव पड़ता है जो कल था: इसने ईमेल पता सेट किया। A अंदर गया, A बाहर आया, इसलिए यह भी अच्छा है।

मेरे मूल उत्तर में मुझे क्या गलत लगा

मैं एक महत्वपूर्ण अंतर आकर्षित करना चाहता हूं (मेरे मूल उत्तर में कुछ गलत हो गया है)। कई सर्वर आपके संशोधन (यदि कोई हो) के साथ, नई इकाई स्थिति को वापस भेजकर आपके REST अनुरोधों का जवाब देंगे। इसलिए, जब आपको यह प्रतिक्रिया वापस मिलती है , तो यह आपके द्वारा कल वापस किए गए से अलग है , क्योंकि ज़िप कोड वह नहीं है जो आपको इस बार मिला है। हालाँकि, आपका अनुरोध केवल ईमेल के साथ, ज़िप कोड से संबंधित नहीं था। तो आपका PATCH दस्तावेज़ अभी भी बेकार है - PATCH में आपके द्वारा भेजा गया ईमेल अब इकाई पर ईमेल पता है।

तो जब PATCH बेकार नहीं है, तब?

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


2
यह वाक्य बिल्कुल सही नहीं है: "लेकिन यह एक आदर्श है: जब भी ए अंदर जाता है, बी हमेशा बाहर आता है"। उदाहरण के लिए, यदि आप GET /users/1पोस्ट ऑफिस से पहले ज़िप कोड अपडेट कर चुके हैं और फिर पोस्ट ऑफिस के अपडेट के बाद फिर से वही GET /users/1अनुरोध करते हैं, तो आपको दो अलग-अलग प्रतिक्रियाएं (अलग ज़िप कोड) मिलेंगी। वही "ए" (GET अनुरोध) में जा रहा है, लेकिन आप अलग परिणाम प्राप्त कर रहे हैं। फिर भी GET अभी भी उदासीन है।
जेसन होएगर

@JasonHoetger GET सुरक्षित है (कोई परिवर्तन नहीं होने का कारण माना जाता है), लेकिन हमेशा ही नहीं होता। इसमे अंतर है। RFC 2616 सेकंड देखें 9.1
दान लोवे

1
@ डनलोवे: निश्चित रूप से बेमिसाल होने की गारंटी है। यह ठीक कहता है कि RFC 2616 की धारा 9.1.2 में, और अद्यतन युक्ति में, RFC 7231 खंड 4.2.2 , कि "इस विनिर्देशन, PUT, DELETE, और सुरक्षित अनुरोध विधियों द्वारा परिभाषित अनुरोध विधियों में से एक हैं।" बेरोजगारी का मतलब यह नहीं है कि "हर बार जब आप एक ही अनुरोध करते हैं तो आपको वैसी ही प्रतिक्रिया मिले"। 7231 4.2.2 आगे कहता है: "अनुरोध को दोहराने का एक ही इरादा प्रभाव होगा, भले ही मूल अनुरोध सफल रहा हो, हालांकि प्रतिक्रिया भिन्न हो सकती है। "
जेसन होएगर

1
@JasonHoetger मैं उस बात को स्वीकार करूंगा, लेकिन मैं यह नहीं देखता कि इसका इस जवाब से क्या लेना-देना है, जिसमें PUT और PATCH पर चर्चा की गई और GET का उल्लेख भी नहीं किया ...
Dan Lowe

1
आह, @JasonHoetger की टिप्पणी ने इसे साफ़ कर दिया: केवल परिणामी अवस्थाएँ, बल्कि प्रतिक्रिया के बजाय, कई विविध विधि अनुरोध समान होने चाहिए।
टॉम रसेल

329

यद्यपि डैन लोव के उत्कृष्ट उत्तर ने ओपी के प्रश्न को PUT और PATCH के बीच अंतर के बारे में पूरी तरह से उत्तर दिया, लेकिन PATCH क्यों नहीं है, इस सवाल का इसका उत्तर काफी हद तक सही नहीं है।

यह दिखाने के लिए कि PATCH क्यों नहीं है, यह बेरोजगारी की परिभाषा ( विकिपीडिया से ) से शुरू करने में मदद करता है :

शब्द बेरोजगारी का उपयोग अधिक व्यापक रूप से एक ऑपरेशन का वर्णन करने के लिए किया जाता है जो एक ही परिणाम का उत्पादन करेगा यदि एक बार या कई बार निष्पादित किया जाता है [...] एक आदर्श फ़ंक्शन वह है जिसमें गुण f (f (x)) = f (x) है किसी भी मूल्य एक्स।

अधिक सुलभ भाषा में, एक आदर्श PATCH को इस रूप में परिभाषित किया जा सकता है: पैच दस्तावेज़ के साथ एक संसाधन को प्राप्त करने के बाद, उसी पैच दस्तावेज़ के साथ एक ही संसाधन के लिए सभी बाद में PATCH कॉल संसाधन को नहीं बदलेगा।

इसके विपरीत, एक गैर-निष्क्रिय ऑपरेशन वह है जिसमें f (f (x))! = F (x) होता है, जिसे PATCH के लिए कहा जा सकता है: पैच डॉक्यूमेंट के साथ एक संसाधन को प्राप्त करने के बाद, बाद में PATCH उसी संसाधन के साथ कॉल करता है। एक ही पैच दस्तावेज़ करते संसाधन बदल जाते हैं।

एक गैर-बेरोजगार PATCH का वर्णन करने के लिए, मान लीजिए कि एक / उपयोगकर्ता संसाधन है, और मान लीजिए कि कॉलिंग GET /usersउपयोगकर्ताओं की एक सूची देता है, वर्तमान में:

[{ "id": 1, "username": "firstuser", "email": "firstuser@example.org" }]

PATCHing / Users / {id} के बजाय, OP के उदाहरण में, मान लीजिए कि सर्वर PATCHing / उपयोगकर्ताओं को अनुमति देता है। आइए इस PATCH अनुरोध को जारी करें:

PATCH /users
[{ "op": "add", "username": "newuser", "email": "newuser@example.org" }]

हमारा पैच दस्तावेज़ सर्वर को निर्देश देता है कि वह उपयोगकर्ताओं newuserकी सूची में एक नया उपयोगकर्ता जोड़ें । यह पहली बार फोन करने के बाद, GET /usersवापस आ जाएगा:

[{ "id": 1, "username": "firstuser", "email": "firstuser@example.org" },
 { "id": 2, "username": "newuser", "email": "newuser@example.org" }]

अब, यदि हम उपरोक्त के रूप में सटीक वही पाच अनुरोध जारी करते हैं, तो क्या होता है? (इस उदाहरण के लिए, मान लें कि / उपयोगकर्ता संसाधन डुप्लिकेट उपयोगकर्ता नामों की अनुमति देता है।) "op" "ऐड" है, इसलिए सूची में एक नया उपयोगकर्ता जोड़ा जाता है, और एक बाद का GET /usersरिटर्न:

[{ "id": 1, "username": "firstuser", "email": "firstuser@example.org" },
 { "id": 2, "username": "newuser", "email": "newuser@example.org" },
 { "id": 3, "username": "newuser", "email": "newuser@example.org" }]

/ उपयोगकर्ता संसाधन फिर से बदल गए हैं , भले ही हमने सटीक उसी समापन बिंदु के खिलाफ एक ही पैटेक जारी किया हो । यदि हमारा PATCH f (x), f (f (x)) f (x) के समान नहीं है, और इसलिए, यह विशेष PATCH बेकार नहीं है

हालांकि, PATCH को बेरोजगार होने की गारंटी नहीं है , लेकिन आपके विशेष सर्वर के सभी PATCH ऑपरेशनों को करने से रोकने के लिए PATCH विनिर्देश में कुछ भी नहीं है। RFC 5789 भी बेमिसाल PATCH अनुरोधों से लाभ की आशा करता है:

एक PATCH अनुरोध को इस तरह से जारी किया जा सकता है, जो कि एक समान हो, जो समान समय-समय पर एक ही संसाधन पर दो PATCH अनुरोधों के बीच टकराव से बुरे परिणामों को रोकने में मदद करता है।

डैन के उदाहरण में, उसका PATCH ऑपरेशन वास्तव में, बेकार है। उस उदाहरण में, हमारे PATCH अनुरोधों के बीच / उपयोगकर्ता / 1 इकाई बदल गई, लेकिन हमारे PATCH अनुरोधों के कारण नहीं ; यह वास्तव में पोस्ट ऑफिस का अलग पैच दस्तावेज था, जिसके कारण ज़िप कोड बदल गया था। पोस्ट ऑफिस का अलग पैटेक एक अलग ऑपरेशन है; अगर हमारा PATCH f (x) है, तो पोस्ट ऑफिस का PATCH g (x) है। Idempotence बताता है कि f(f(f(x))) = f(x), लेकिन इस बारे में कोई गारंटी नहीं देता है f(g(f(x)))


11
यह मानते हुए कि सर्वर भी PUT को जारी करने की अनुमति देता है /users, इससे PUT न के बराबर हो जाएगा। यह सब नीचे आता है कि कैसे सर्वर अनुरोधों को संभालने के लिए डिज़ाइन किया गया है।
उज़ैर साजिद

13
इसलिए, हम केवल PATCH संचालन के साथ एक एपीआई का निर्माण कर सकते हैं। फिर, संसाधनों पर CRUD कार्रवाई करने के लिए http VERBS का उपयोग करने का REST सिद्धांत क्या बन जाता है? क्या हम यहाँ के पाटीदार सज्जनों को ओवर-कम नहीं कर रहे हैं?
बोह्र

6
यदि PUT को किसी संग्रह (जैसे /users) पर लागू किया जाता है , तो किसी भी PUT अनुरोध को उस संग्रह की सामग्री को बदलना चाहिए। तो एक PUT को /usersउपयोगकर्ताओं के संग्रह की उम्मीद करनी चाहिए और अन्य सभी को हटा देना चाहिए। यह आलंकारिक है। यह संभावना नहीं है कि आप / उपयोगकर्ताओं के समापन बिंदु पर ऐसा काम करेंगे। लेकिन ऐसा कुछ /users/1/emailsसंग्रह हो सकता है और यह पूरे संग्रह को एक नए के साथ बदलने की अनुमति देने के लिए पूरी तरह से मान्य हो सकता है।
वेक्टरजोन

5
यद्यपि यह उत्तर आलस्य का एक बड़ा उदाहरण प्रदान करता है, मेरा मानना ​​है कि यह विशिष्ट आरईएस परिदृश्यों में पानी की कमी कर सकता है। इस मामले में आपके पास एक अतिरिक्त opकार्रवाई के साथ एक PATCH अनुरोध है जो विशिष्ट सर्वर साइड लॉजिक को ट्रिगर कर रहा है। यह opसर्वर साइड वर्कफ़्लोज़ को ट्रिगर करने के लिए फ़ील्ड के लिए विशिष्ट मानों के बारे में जानने के लिए सर्वर और क्लाइंट की आवश्यकता होगी । अधिक सरल REST परिदृश्यों में, इस प्रकार की opकार्यक्षमता खराब अभ्यास है और संभवतः HTTP क्रियाओं के माध्यम से इसे सीधे संभाला जाना चाहिए।
ivandov

7
मैं कभी भी एक संग्रह के खिलाफ एक PATCH, केवल POST और DELETE जारी करने पर विचार नहीं करूंगा। क्या वास्तव में ऐसा कभी हुआ है? क्या इसलिए PATCH को सभी व्यावहारिक उद्देश्यों के लिए आदर्श माना जा सकता है?
टॉम रसेल

72

मैं इसके बारे में भी उत्सुक था और कुछ दिलचस्प लेख मिला। हो सकता है कि मैं आपके प्रश्न का पूरी तरह से उत्तर न दूं, लेकिन यह कम से कम कुछ और जानकारी प्रदान करता है।

http://restful-api-design.readthedocs.org/en/latest/methods.html

HTTP RFC निर्दिष्ट करता है कि PUT को अनुरोध इकाई के रूप में एक पूर्ण नया संसाधन प्रतिनिधित्व लेना चाहिए। इसका मतलब यह है कि यदि उदाहरण के लिए केवल कुछ विशेषताएं प्रदान की जाती हैं, तो उन्हें हटा दिया जाना चाहिए (यानी शून्य पर सेट)।

उसे देखते हुए, फिर एक PUT को पूरी वस्तु भेजनी चाहिए। उदाहरण के लिए,

/users/1
PUT {id: 1, username: 'skwee357', email: 'newemail@domain.com'}

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

/users/1
PUT {id: 1, email: 'newemail@domain.com'}

अब, यदि PUT को युक्ति के अनुसार डिज़ाइन किया गया था, तो PUT उपयोगकर्ता नाम को शून्य करने के लिए सेट करेगा और आपको निम्न वापस मिलेगा।

{id: 1, username: null, email: 'newemail@domain.com'}

जब आप एक PATCH का उपयोग करते हैं, तो आप केवल आपके द्वारा निर्दिष्ट फ़ील्ड को अपडेट करते हैं और बाकी को अपने उदाहरण में अकेले छोड़ देते हैं।

PATCH पर निम्नलिखित टेक थोड़ा अलग है जो मैंने पहले कभी नहीं देखा है।

http://williamdurand.fr/2014/02/14/please-do-not-patch-like-an-idiot/

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

PATCH /users/123

[
    { "op": "replace", "path": "/email", "value": "new.email@example.org" }
]

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

इसके साथ लेख समाप्त होता है।

यह ध्यान देने योग्य है कि PATCH वास्तव में REST API के लिए डिज़ाइन नहीं किया गया है, क्योंकि क्षेत्ररक्षण का शोध प्रबंध आंशिक रूप से संसाधनों को संशोधित करने का कोई तरीका निर्धारित नहीं करता है। लेकिन, रॉय फील्डिंग ने खुद कहा कि PATCH कुछ था [वह] प्रारंभिक HTTP / 1.1 प्रस्ताव के लिए बनाया गया था क्योंकि आंशिक PUT कभी भी RESTful नहीं है। सुनिश्चित करें कि आप पूर्ण प्रतिनिधित्व स्थानांतरित नहीं कर रहे हैं, लेकिन REST को वैसे भी पूर्ण होने के लिए प्रतिनिधित्व की आवश्यकता नहीं है।

अब, मुझे नहीं पता कि क्या मैं विशेष रूप से लेख के साथ सहमत हूं क्योंकि कई टिप्पणीकार इंगित करते हैं। आंशिक प्रतिनिधित्व पर भेजना आसानी से परिवर्तनों का वर्णन हो सकता है।

मेरे लिए, मुझे PATCH का उपयोग करने पर मिलाया गया है। अधिकांश भाग के लिए, मैं PUT को PATCH के रूप में मानूंगा क्योंकि मैंने अब तक जो एकमात्र वास्तविक अंतर देखा है, वह यह है कि PUT को लापता मानों को शून्य में सेट करना चाहिए। यह करने के लिए 'सबसे सही' तरीका नहीं हो सकता है, लेकिन सौभाग्य सही कोडिंग।


7
यह जोड़ने के लायक हो सकता है: विलियम डूरंड के लेख में (और rfc 6902) ऐसे उदाहरण हैं जहां "op" "add" है। यह स्पष्ट रूप से उदासीन नहीं है।
जोहान्स ब्रोडवॉल

2
या आप आसान बना सकते हैं और इसके बजाय RFC 7396 मर्ज पैच का उपयोग कर सकते हैं और पैच JSON के निर्माण से बच सकते हैं।
पायोतर कुला

nosql तालिकाओं के लिए, पैच और पुट के बीच अंतर महत्वपूर्ण है, क्योंकि nosql में कोई कॉलम नहीं है
stackdave

18

PUT और PATCH के बीच अंतर यह है कि:

  1. PUT को बेरोजगार होना आवश्यक है। इसे प्राप्त करने के लिए, आपको संपूर्ण संपूर्ण संसाधन अनुरोध निकाय में रखना होगा।
  2. PATCH न के बराबर हो सकता है। इसका मतलब यह है कि यह कुछ मामलों में उदासीन भी हो सकता है, जैसे कि आपके द्वारा वर्णित मामले।

PATCH को सर्वर को कैसे संशोधित करना है यह बताने के लिए कुछ "पैच भाषा" की आवश्यकता होती है। कॉल करने वाले और सर्वर को कुछ "ऑपरेशंस" को परिभाषित करने की आवश्यकता होती है जैसे "ऐड", "रिप्लेस", "डिलीट"। उदाहरण के लिए:

GET /contacts/1
{
  "id": 1,
  "name": "Sam Kwee",
  "email": "skwee357@olddomain.com",
  "state": "NY",
  "zip": "10001"
}

PATCH /contacts/1
{
 [{"operation": "add", "field": "address", "value": "123 main street"},
  {"operation": "replace", "field": "email", "value": "abc@myemail.com"},
  {"operation": "delete", "field": "zip"}]
}

GET /contacts/1
{
  "id": 1,
  "name": "Sam Kwee",
  "email": "abc@myemail.com",
  "state": "NY",
  "address": "123 main street",
}

स्पष्ट "ऑपरेशन" फ़ील्ड का उपयोग करने के बजाय, पैच भाषा इसे सम्मेलनों को परिभाषित करके इसे अंतर्निहित कर सकती है जैसे:

PATCH अनुरोध निकाय में:

  1. किसी फ़ील्ड के अस्तित्व का अर्थ है उस फ़ील्ड को "बदलना" या "जोड़ना"।
  2. यदि किसी फ़ील्ड का मान शून्य है, तो इसका मतलब है कि उस फ़ील्ड को हटा दें।

उपरोक्त सम्मेलन के साथ, उदाहरण में PATCH निम्नलिखित रूप ले सकता है:

PATCH /contacts/1
{
  "address": "123 main street",
  "email": "abc@myemail.com",
  "zip":
}

जो अधिक संक्षिप्त और उपयोगकर्ता के अनुकूल लगता है। लेकिन उपयोगकर्ताओं को अंतर्निहित सम्मेलन के बारे में पता होना चाहिए।

ऊपर उल्लिखित ऑपरेशनों के साथ, PATCH अभी भी उदासीन है। लेकिन अगर आप संचालन को परिभाषित करते हैं जैसे: "वेतन वृद्धि" या "परिशिष्ट", तो आप आसानी से देख सकते हैं कि यह अब बेकार नहीं होगा।


7

TLDR - डंबल डाउन संस्करण

PUT => मौजूदा संसाधन के लिए सभी नई विशेषताएँ सेट करें।

PATCH => आंशिक रूप से एक मौजूदा संसाधन (सभी विशेषताओं की आवश्यकता नहीं) को अपडेट करें।


3

मुझे पहले से टिप्पणी में उद्धृत RFC 7231 सेक्शन 4.2.2 पर अधिक बारीकी से उद्धृत करने और टिप्पणी करने दें:

एक अनुरोध विधि को "निष्पादनीय" माना जाता है यदि उस विधि के साथ कई समान अनुरोधों के सर्वर पर इच्छित प्रभाव एकल एकल अनुरोध के लिए प्रभाव के समान है। इस विनिर्देशन, PUT, DELETE, और सुरक्षित अनुरोध विधियों द्वारा परिभाषित अनुरोध विधियों में से एक हैं।

(...)

आदर्श तरीके को प्रतिष्ठित किया जाता है क्योंकि क्लाइंट के सर्वर की प्रतिक्रिया को पढ़ने में सक्षम होने से पहले संचार विफलता होने पर अनुरोध स्वचालित रूप से दोहराया जा सकता है। उदाहरण के लिए, यदि कोई ग्राहक एक PUT अनुरोध भेजता है और किसी भी प्रतिक्रिया के प्राप्त होने से पहले अंतर्निहित कनेक्शन बंद हो जाता है, तो ग्राहक एक नया कनेक्शन स्थापित कर सकता है और idempotent अनुरोध को पुन: प्रयास कर सकता है। यह जानता है कि अनुरोध को दोहराने का एक ही इरादा प्रभाव होगा, भले ही मूल अनुरोध सफल हो, हालांकि प्रतिक्रिया भिन्न हो सकती है।

तो, एक बेकार विधि के बार-बार अनुरोध के बाद "वही" क्या होना चाहिए? न सर्वर राज्य, न ही सर्वर प्रतिक्रिया, लेकिन इच्छित प्रभाव । विशेष रूप से, विधि को "ग्राहक के दृष्टिकोण से" बेरोजगार होना चाहिए। अब, मुझे लगता है कि इस दृष्टिकोण से पता चलता है कि डैन लोव के उत्तर में अंतिम उदाहरण , जिसे मैं यहाँ पर टालना नहीं चाहता हूँ, वास्तव में यह दर्शाता है कि एक PATCH अनुरोध अप्रतिष्ठित हो सकता है (उदाहरण से अधिक प्राकृतिक तरीके से) जेसन होएगर का जवाब )।

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

PATCH /users/1
{"email": "skwee357@newdomain.com"}

चूंकि यह एकमात्र सुधार है। अब, कुछ नेटवर्क समस्या के कारण अनुरोध विफल हो जाता है और कुछ घंटों बाद स्वचालित रूप से फिर से प्रस्तुत किया जाता है। इस बीच, एक अन्य ग्राहक ने (गलती से) उपयोगकर्ता 1 के ज़िप को संशोधित कर दिया है। फिर, दूसरी बार उसी पैटच अनुरोध को भेजने से ग्राहक के इच्छित प्रभाव को प्राप्त नहीं होता है , क्योंकि हम एक गलत ज़िप के साथ समाप्त होते हैं। इसलिए RFC के अर्थ में यह विधि बेकार नहीं है।

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


2

मेरी विनम्र राय में, मूर्खता का अर्थ है:

  • डाल:

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

  • PATCH:

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

किसी वस्तु को निम्नानुसार परिभाषित करें:

कार: - रंग: काला, प्रकार: पालकी, - सीटें: 5

मैं इसके साथ पैच:

{लाल रंग'}

परिणामी वस्तु है:

कार: - रंग: लाल, प्रकार: पालकी, - सीटें: 5

फिर, कुछ अन्य उपयोगकर्ताओं ने इस कार को पैच किया:

{टाइप: 'हैचबैक'}

इसलिए, परिणामी वस्तु है:

कार: - रंग: लाल, - प्रकार: हैचबैक, - सीटें: 5

अब, अगर मैं इस ऑब्जेक्ट को फिर से पैच करता हूं:

{लाल रंग'}

परिणामी वस्तु है:

कार: - रंग: लाल, - प्रकार: हैचबैक, - सीटें: 5

जो मुझे पहले मिला है, उसके लिए क्या अलग है!

यही कारण है कि पीएटीएचए बेमियादी नहीं है जबकि पीयूटी बेकार है।


1

निष्पादकता पर चर्चा समाप्त करने के लिए, मुझे यह ध्यान देना चाहिए कि व्यक्ति दो प्रकार से REST संदर्भ में आलंबनशीलता को परिभाषित कर सकता है। आइए पहले कुछ चीजों को औपचारिक रूप दें:

एक संसाधन एक फ़ंक्शन है जिसके कोडोमैन तार के वर्ग हैं। दूसरे शब्दों में, एक संसाधन एक सबसेट है String × Any, जहाँ सभी कुंजियाँ अद्वितीय हैं। संसाधनों के वर्ग को कहते हैं Res

संसाधनों पर एक रीस्ट ऑपरेशन, एक फ़ंक्शन है f(x: Res, y: Res): Res। REST ऑपरेशन के दो उदाहरण हैं:

  • PUT(x: Res, y: Res): Res = x, तथा
  • PATCH(x: Res, y: Res): Res, जो काम करता है PATCH({a: 2}, {a: 1, b: 3}) == {a: 2, b: 3}

(यह परिभाषा विशेष रूप से के बारे में बहस करने डिज़ाइन किया गया है PUTऔर POST, और जैसे पर ज्यादा मतलब नहीं है GETऔर POST, के रूप में यह दृढ़ता के बारे में परवाह नहीं है)।

अब, फिक्सिंग x: Res(अनौपचारिक रूप से, क्यूरिंग का उपयोग करके), PUT(x: Res)और PATCH(x: Res)प्रकार के अनिवारीट कार्य हैं Res → Res

  1. एक समारोह g: Res → Resहै कहा जाता है विश्व स्तर पर idempotent , जब g ○ g == gकिसी के लिए, यानी y: Res, g(g(y)) = g(y)

  2. x: Resएक संसाधन दें , और k = x.keys। एक फंक्शन g = f(x)को लेफ्ट इडम्पोटेंट कहा जाता है , जब प्रत्येक के लिए y: Res, हमारे पास होता है g(g(y))|ₖ == g(y)|ₖ। इसका मूल रूप से मतलब है कि परिणाम समान होना चाहिए, अगर हम लागू कुंजियों को देखते हैं।

तो, PATCH(x)विश्व स्तर पर बेरोजगार नहीं है, लेकिन छोड़ दिया गया है। और बाईं ओर की उदासीनता वह चीज है जो यहां मायने रखती है: यदि हम संसाधन की कुछ कुंजियों को पैच करते हैं, तो हम चाहते हैं कि यदि हम इसे फिर से पैच करते हैं, तो हम उन चाबियों को समान कर दें, और हम बाकी संसाधन की परवाह नहीं करते हैं।

और जब RFC PATCH के लिए बेरोजगार नहीं होने की बात कर रहा है, तो यह वैश्विक मूर्खता के बारे में बात कर रहा है। खैर, यह अच्छा है कि यह विश्व स्तर पर बेरोजगार नहीं है, अन्यथा यह एक टूटी हुई कार्रवाई होती।


अब, जेसन होएगर का जवाब यह प्रदर्शित करने की कोशिश कर रहा है कि PATCH भी बेकार नहीं है, लेकिन ऐसा करने के लिए बहुत सी चीजों को तोड़ रहा है:

  • सबसे पहले, PATCH का उपयोग एक सेट पर किया जाता है, हालांकि PATCH को मानचित्रों / शब्दकोशों / कुंजी-मूल्य वस्तुओं पर काम करने के लिए परिभाषित किया गया है।
  • यदि कोई वास्तव में सेट करने के लिए PATCH को लागू करना चाहता है, तो एक प्राकृतिक अनुवाद है जिसका उपयोग किया जाना चाहिए:, के t: Set<T> → Map<T, Boolean>साथ परिभाषित x in A iff t(A)(x) == True। इस परिभाषा का उपयोग करते हुए, पैचिंग को छोड़ दिया गया है।
  • उदाहरण में, इस अनुवाद का उपयोग नहीं किया गया था, इसके बजाय, PATCH एक POST की तरह काम करता है। सबसे पहले, वस्तु के लिए एक आईडी क्यों बनाई गई है? और यह कब उत्पन्न होता है? यदि ऑब्जेक्ट पहले सेट के तत्वों की तुलना में है, और यदि कोई मिलान वस्तु नहीं मिलती है, तो आईडी उत्पन्न होती है, फिर से प्रोग्राम को अलग तरीके से काम करना चाहिए ( {id: 1, email: "me@site.com"}मिलान होना चाहिए {email: "me@site.com"}, अन्यथा प्रोग्राम हमेशा टूट जाता है और PATCH संभवतः नहीं कर सकता है पैच)। यदि सेट के खिलाफ जांच करने से पहले आईडी उत्पन्न होती है, तो फिर से कार्यक्रम टूट जाता है।

PUT के गैर-बेरोजगार होने के उदाहरणों को इस उदाहरण में तोड़ दी गई आधी चीजों को तोड़कर बनाया जा सकता है:

  • उत्पन्न अतिरिक्त सुविधाओं के साथ एक उदाहरण संस्करण होगा। किसी एकल ऑब्जेक्ट पर परिवर्तनों की संख्या का रिकॉर्ड रख सकते हैं। इस मामले में, पीयूटी बेकार नहीं है: पहली बार PUT /user/12 {email: "me@site.com"}में परिणाम {email: "...", version: 1}, और {email: "...", version: 2}दूसरी बार।
  • आईडी के साथ मेसिंग, हर बार ऑब्जेक्ट अपडेट होने पर एक नई आईडी जेनरेट की जा सकती है, जिसके परिणामस्वरूप नॉन-इम्पोटेंट पीयूटी होता है।

उपरोक्त सभी उदाहरण प्राकृतिक उदाहरण हैं जिनका सामना हो सकता है।


मेरा अंतिम बिंदु यह है कि PATCH विश्व स्तर पर बेकार नहीं होना चाहिए , अन्यथा आपको वांछित प्रभाव नहीं देगा। आप अपने उपयोगकर्ता के ईमेल पते को बदलना चाहते हैं, बाकी जानकारी को छुए बिना, और आप उसी संसाधन तक पहुंचने वाले किसी अन्य पक्ष के परिवर्तनों को अधिलेखित नहीं करना चाहते हैं।


-1

एक अतिरिक्त जानकारी जो मैं बस जोड़ना चाहता हूं वह यह है कि एक PATCH अनुरोध PUT अनुरोध की तुलना में कम बैंडविड्थ का उपयोग करता है क्योंकि डेटा का एक हिस्सा पूरी इकाई नहीं भेजा जाता है। इसलिए केवल विशिष्ट रिकॉर्ड जैसे (1-3 रिकॉर्ड) के अपडेट के लिए एक PATCH अनुरोध का उपयोग करें, जबकि PUT डेटा की एक बड़ी मात्रा को अपडेट करने के लिए अनुरोध करें। यही है, बहुत ज्यादा मत सोचो या इसके बारे में बहुत अधिक चिंता मत करो।

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