2015-02-19 8 views
42

मान लें कि एसोसिएशन रिलेशनशिप के साथ दो संसाधन Binder और Doc हैं जिसका अर्थ है कि Doc और Binder स्वयं ही खड़े हैं। DocBinder और Binder से संबंधित हो सकता है या नहीं हो सकता है।REST API - एकल अनुरोध में थोक बनाएं या अपडेट करें

मैं एक REST API कि उपयोगकर्ता निम्नलिखित की तरह एक ही अनुरोध में Doc रों, का एक संग्रह को भेजने के लिए अनुमति देता है, डिजाइन करने के लिए करना चाहते हैं:

{ 
    "docs": [ 
    {"doc_number": 1, "binder": 1}, 
    {"doc_number": 5, "binder": 8}, 
    {"doc_number": 6, "binder": 3} 
    ] 
} 

और docs में प्रत्येक दस्तावेज़ के लिए,

  • doc तो Binder
  • तो doc हिरण को असाइन मौजूद है अस्तित्व में नहीं है, इसे बनाएं और फिर इसे

मैं वास्तव में उलझन में हूं कि इसे कैसे कार्यान्वित किया जाना चाहिए।

  • उपयोग करने के लिए HTTP विधि क्या है?
  • क्या प्रतिक्रिया कोड वापस किया जाना चाहिए?
  • क्या यह आरईएसटी के लिए भी योग्य है?
  • यूआरआई कैसा दिखता है? /binders/docs?
  • थोक अनुरोध को संभालना, क्या होगा यदि कुछ आइटम त्रुटियां बढ़ाते हैं लेकिन दूसरा गुजरता है। क्या प्रतिक्रिया कोड वापस किया जाना चाहिए? क्या थोक ऑपरेशन परमाणु होना चाहिए?

उत्तर

25

मुझे लगता है कि आप इसे संभालने के लिए पोस्ट या पैच विधि का उपयोग कर सकते हैं क्योंकि वे आम तौर पर इसके लिए डिज़ाइन करते हैं।

  • एक POST विधि का प्रयोग आम तौर पर जब सूची संसाधन पर इस्तेमाल किया एक तत्व जोड़ने के लिए प्रयोग किया जाता है, लेकिन आप भी इस विधि के लिए कई कार्यों का समर्थन कर सकते हैं। यह उत्तर देखें: How to Update a REST Resource Collection। आप इनपुट के लिए अलग-अलग प्रतिनिधित्व स्वरूपों का भी समर्थन कर सकते हैं (यदि वे किसी सरणी या एकल तत्वों से मेल खाते हैं)।

    मामले में, अद्यतन का वर्णन करने के लिए अपने प्रारूप को परिभाषित करना आवश्यक नहीं है।

  • PATCH विधि का उपयोग करना भी उपयुक्त है क्योंकि संबंधित अनुरोध आंशिक अद्यतन से मेल खाते हैं। RFC5789 (http://tools.ietf.org/html/rfc5789) के अनुसार:

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

    मामले में, आपको आंशिक अद्यतन का वर्णन करने के लिए अपने प्रारूप को परिभाषित करना होगा।

मुझे लगता है कि इस मामले में, POST और PATCH काफी समान के बाद से आप वास्तव में प्रत्येक तत्व के लिए ऐसा करने के लिए आपरेशन वर्णन करने के लिए की जरूरत नहीं है कर रहे हैं। मैं कहूंगा कि यह भेजने के लिए प्रतिनिधित्व के प्रारूप पर निर्भर करता है।

PUT का मामला थोड़ा कम स्पष्ट है। वास्तव में, एक विधि PUT का उपयोग करते समय, आपको पूरी सूची प्रदान करनी चाहिए। वास्तव में, अनुरोध में प्रदान किया गया प्रतिनिधित्व सूची संसाधन एक के प्रतिस्थापन में होगा।

आपके पास संसाधन पथ से संबंधित दो विकल्प हो सकते हैं।

  • डॉक सूची

इस मामले में के लिए संसाधन पथ का उपयोग करके आप स्पष्ट रूप प्रतिनिधित्व आप अनुरोध में प्रदान में एक बांधने की मशीन के साथ किए गए दस्तावेज़ों की लिंक देना।

यहां इस /docs के लिए नमूना मार्ग है।

इस तरह के दृष्टिकोण की सामग्री विधि POST के लिए हो सकता है:

[ 
    { "doc_number": 1, "binder": 4, (other fields in the case of creation) }, 
    { "doc_number": 2, "binder": 4, (other fields in the case of creation) }, 
    { "doc_number": 3, "binder": 5, (other fields in the case of creation) }, 
    (...) 
] 
  • बांधने की मशीन तत्व के उप संसाधन पथ का उपयोग करना

इसके अलावा आप भी करने के लिए उप मार्गों लाभ उठाने के लिए विचार कर सकते हैं दस्तावेज़ और बाइंडर्स के बीच लिंक का वर्णन करें। एक दस्तावेज़ और बाइंडर के बीच संबंध के संबंध में संकेत अब अनुरोध सामग्री के भीतर निर्दिष्ट नहीं किया जाना चाहिए।

यहां इस /binder/{binderId}/docs के लिए नमूना मार्ग है। इस मामले में, दस्तावेज़ POST या PATCH के साथ दस्तावेज़ों की एक सूची भेजना दस्तावेज़ मौजूद होने के बाद पहचानकर्ता binderId के साथ बाइंडर को संलग्न करेगा यदि यह अस्तित्व में नहीं है।

इस तरह के दृष्टिकोण की सामग्री विधि POST के लिए हो सकता है:

[ 
    { "doc_number": 1, (other fields in the case of creation) }, 
    { "doc_number": 2, (other fields in the case of creation) }, 
    { "doc_number": 3, (other fields in the case of creation) }, 
    (...) 
] 

प्रतिक्रिया के बारे में, यह प्रतिक्रिया और त्रुटियों वापस जाने के लिए के स्तर को परिभाषित करने के लिए आप पर निर्भर है। मुझे दो स्तर दिखाई देते हैं: स्थिति स्तर (वैश्विक स्तर) और पेलोड स्तर (पतला स्तर)। यह भी परिभाषित करने के लिए आप पर निर्भर है कि आपके अनुरोध से संबंधित सभी आवेषण/अपडेट परमाणु होना चाहिए या नहीं।

  • परमाणु

इस मामले में, आप HTTP स्थिति का लाभ उठाने कर सकते हैं। अगर सब कुछ ठीक हो जाता है, तो आपको स्थिति 200 मिलती है। यदि नहीं, तो 400 जैसी कोई अन्य स्थिति यदि प्रदान किया गया डेटा सही नहीं है (उदाहरण के लिए बाइंडर आईडी मान्य नहीं है) या कुछ और।

  • गैर परमाणु

इस मामले में, एक स्थिति 200 लौटा दी जाएगी और यह वर्णन करने के लिए क्या किया गया था और जहां त्रुटियों अंत में पाए जाते हैं प्रतिक्रिया प्रतिनिधित्व पर निर्भर है। थोक अद्यतन के लिए अपने आरईएसटी एपीआई में लोचदार खोज का अंत बिंदु है। यह आपको इस स्तर पर कुछ विचार दे सकता है: http://www.elasticsearch.org/guide/en/elasticsearch/guide/current/bulk.html

  • अतुल्यकालिक

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

परिष्करण से पहले, मैं यह भी देखना चाहता हूं कि ओडाटा विनिर्देश नेविगेशन लिंक नामक सुविधा वाले इकाइयों के बीच संबंधों के संबंध में इस मुद्दे को संबोधित करता है। शायद आप इसे देख सकते हैं ;-)

निम्न लिंक आपको भी मदद कर सकता है: https://templth.wordpress.com/2014/12/15/designing-a-web-api/

आशा है कि यह आप में मदद करता है, थियरी

10

PUT ing

PUT /binders/{id}/docs या अद्यतन, और एक बांधने की मशीन

उदा .:

PUT /binders/1/docs HTTP/1.1 
{ 
    "docNumber" : 1 
} 

PATCH ing के लिए एक एकल दस्तावेज़ संबंधित

PATCH /docs दस्तावेज़ बनाएं यदि वे मौजूद हैं और उन्हें बाइंडरों

जैसे से संबंधित नहीं:

PATCH /docs HTTP/1.1 
[ 
    { "op" : "add", "path" : "/binder/1/docs", "value" : { "doc_number" : 1 } }, 
    { "op" : "add", "path" : "/binder/8/docs", "value" : { "doc_number" : 8 } }, 
    { "op" : "add", "path" : "/binder/3/docs", "value" : { "doc_number" : 6 } } 
] 

मैं अतिरिक्त अंतर्दृष्टि बाद में शामिल करेंगे, लेकिन इस बीच आप, करना चाहते हैं RFC 5789, RFC 6902 पर एक नजर है, तो और विलियम डुरंड की Please. Don't Patch Like an Idiot ब्लॉग प्रविष्टि।

+1

कभी-कभी ग्राहक को थोक ऑपरेशन की आवश्यकता होती है और यह परवाह नहीं करना चाहता कि संसाधन वहां है या नहीं। जैसा कि मैंने सवाल में कहा था, ग्राहक 'डॉक्स' का एक गुच्छा भेजना चाहता है और उन्हें 'बाइंडर्स' से जोड़ना चाहता है। ग्राहक बाइंडर्स बनाना चाहता है अगर वे मौजूद नहीं हैं और यदि वे करते हैं तो एसोसिएशन बनाते हैं। एक सिंगल बल्क अनुरोध में। – norbertpy

18

आपको शायद पोस्ट या पैच का उपयोग करने की आवश्यकता होगी, क्योंकि यह संभावना नहीं है कि एक ही अनुरोध जो एकाधिक संसाधनों को अद्यतन और बनाता है, वह बेवकूफ होगा।

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

आप 200 का उपयोग कर सकते हैं।आप 207 - Multi Status

का उपयोग भी कर सकते हैं यह एक शानदार तरीके से किया जा सकता है। कुंजी, मेरी राय में, कुछ संसाधन है जो अद्यतन/बनाने के लिए दस्तावेजों के एक सेट को स्वीकार करने के लिए डिज़ाइन किया गया है।

यदि आप पैच विधि का उपयोग करते हैं तो मुझे लगता है कि आपका ऑपरेशन परमाणु होना चाहिए। यानी मैं 207 स्टेटस कोड का उपयोग नहीं करता और फिर प्रतिक्रिया निकाय में सफलताओं और असफलताओं की रिपोर्ट करता हूं। यदि आप POST ऑपरेशन का उपयोग करते हैं तो 207 दृष्टिकोण व्यवहार्य है। संचार करने के लिए आपको अपने स्वयं के प्रतिक्रिया निकाय को डिजाइन करना होगा और कौन सा असफल रहा। मुझे मानकीकृत एक के बारे में पता नहीं है।

+0

आपको बहुत बहुत धन्यवाद। 'यह एक यथार्थवादी तरीके से किया जा सकता है' क्या आपका मतलब है कि अद्यतन और निर्माण अलग से किया जाना चाहिए? – norbertpy

+0

@norbertpy किसी संसाधन पर किसी प्रकार का लेखन ऑपरेशन करने से अन्य संसाधनों को अद्यतन और एक अनुरोध से बनाया जा सकता है। आरईएसटी के साथ कोई मुद्दा नहीं है। वाक्यांश की मेरी पसंद इसलिए थी क्योंकि कुछ ढांचे बहु-भाग दस्तावेजों में HTTP अनुरोधों को क्रमबद्ध करके और फिर बैच के रूप में क्रमबद्ध HTTP अनुरोध भेजकर थोक संचालन को लागू करते हैं। मुझे लगता है कि दृष्टिकोण संसाधन पहचान आरईएसटी बाधा का उल्लंघन करता है। –

1

एक परियोजना मैं काम हम कुछ हम 'बैच के अनुरोध बुलाया लागू इस समस्या का समाधान पर हैं।

[ 
    { 
     path: '/docs', 
     method: 'post', 
     body: { 
     doc_number: 1, 
     binder: 1 
     } 
    }, 
    { 
     path: '/docs', 
     method: 'post', 
     body: { 
     doc_number: 5, 
     binder: 8 
     } 
    }, 
    { 
     path: '/docs', 
     method: 'post', 
     body: { 
     doc_number: 6, 
     binder: 3 
     } 
    }, 
] 

प्रतिसाद स्थिति कोड 207 (मल्टी स्थिति) है और इस तरह दिखता है:

[ 
    { 
     path: '/docs', 
     method: 'post', 
     body: { 
     doc_number: 1, 
     binder: 1 
     } 
     status: 200 
    }, 
    { 
     path: '/docs', 
     method: 'post', 
     body: { 
     error: { 
      msg: 'A document with doc_number 5 already exists' 
      ... 
     } 
     }, 
     status: 409 
    }, 
    { 
     path: '/docs', 
     method: 'post', 
     body: { 
     doc_number: 6, 
     binder: 3 
     }, 
     status: 200 
    }, 
] 

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

फेसबुक और गूगल समान कार्यान्वयन है:
https://developers.google.com/gmail/api/guides/batch
https://developers.facebook.com/docs/graph-api/making-multiple-requests

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

  1. दस्तावेज़ आप में भेजने से बदला गया (अनुरोध में अर्थात लापता गुण को हटा दिया जाएगा और पहले से ही ओवरराइट मौजूदा)?
  2. आपके द्वारा भेजे गए दस्तावेज़ के साथ विलय (यानी अनुरोध में अनुपलब्ध गुणों को हटाया नहीं जाएगा और पहले से ही मौजूदा गुणों को अधिलेखित किया जाएगा)?

यदि आप वैकल्पिक 1 से व्यवहार चाहते हैं तो आपको POST का उपयोग करना चाहिए और यदि आप विकल्प 2 से व्यवहार चाहते हैं तो आपको PUT का उपयोग करना चाहिए।

http://restcookbook.com/HTTP%20Methods/put-vs-post/

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

+3

प्रूफ-ऑफ-कॉन्सेप्ट के साथ-साथ Google और फेसबुक लिंक के लिए इस उत्तर की तरह। लेकिन पोस्ट या पुट के बारे में अंतिम भाग से असहमत हैं। 2 मामलों में इस उत्तर का उल्लेख किया गया है, पहला व्यक्ति पुट होना चाहिए, और दूसरा पैच होना चाहिए। – RayLuo

+0

@RayLuo, क्या आप समझा सकते हैं कि हमें पोस्ट और पुट के अलावा पैच की आवश्यकता क्यों है? –

+1

क्योंकि पैच का आविष्कार यही था। आप [इस परिभाषा] को पढ़ सकते हैं (https://tools.ietf.org/html/rfc5789#section-2) और देखें कि पुट और पैच आपके 2 बुलेटपॉइंट्स से कैसे मेल खाते हैं। – RayLuo

संबंधित मुद्दे