रीस्टफुल एपीआई में कमांड पैटर्न को लागू करना


12

मैं HTTP API डिज़ाइन करने की प्रक्रिया में हूँ, उम्मीद है कि इसे यथासंभव Restful बनाऊँगा।

कुछ क्रियाएं हैं जो कार्यक्षमता कुछ संसाधनों पर फैलती हैं, और कुछ समय के लिए पूर्ववत होना आवश्यक है।

मैंने खुद से सोचा, यह एक कमांड पैटर्न की तरह लगता है, लेकिन मैं इसे एक संसाधन में कैसे मॉडल कर सकता हूं?

मैं एक्सएक्सएशन नामक एक नए संसाधन का परिचय करूंगा, जैसे डिपॉजिशन, जो कुछ इस तरह से बनाया जाएगा

POST /card/{card-id}/account/{account-id}/Deposit
AmountToDeposit=100, different parameters...

यह वास्तव में एक नया डिपाजिटेशन बनाएगा और इसे Do / Execute विधि सक्रिय करेगा। इस मामले में, 201 निर्मित HTTP स्थिति लौटने का मतलब है कि कार्रवाई सफलतापूर्वक निष्पादित की गई है।

बाद में यदि कोई ग्राहक अपने कार्य विवरण को देख सकता है

GET /action/{action-id}

अपडेट / पीयूटी को अवरुद्ध किया जाना चाहिए मुझे लगता है, क्योंकि यह यहां प्रासंगिक नहीं है।

और कार्रवाई को पूर्ववत करने के लिए, मैंने उपयोग करने के बारे में सोचा

DELETE /action/{action-id}

जो वास्तव में संबंधित वस्तु के पूर्ववत विधि को कॉल करेगा, और इसे स्थिति बदल देगा।

मान लीजिए कि मैं केवल एक Do-Undo से खुश हूं, मुझे Redo की आवश्यकता नहीं है।

क्या यह दृष्टिकोण ठीक है?

क्या इसका उपयोग न करने के कोई कारण हैं?

क्या यह क्लाइंट्स के POV से समझा जाता है?


संक्षिप्त उत्तर, यह REST नहीं है।
इवान प्लाइस

3
@ EvanPlaice उस पर विस्तार से ध्यान देता है? बिल्कुल यही सवाल है।
मिथिर

1
मैं एक जवाब में विस्तृत होगा, लेकिन गैरी का जवाब पहले से ही सबसे अधिक / सभी को शामिल करता है जो मैं जोड़ूंगा। मैं कहता हूं कि यह बाकी नहीं है क्योंकि यूआरआई केवल संसाधनों का प्रतिनिधित्व करने वाले हैं (अर्थात क्रियाएं नहीं)। क्रियाएँ GET / POST / PUT / DELETE / HEAD के माध्यम से नियंत्रित की जाती हैं। OOP इंटरफ़ेस के रूप में REST के बारे में सोचें। एपीआई को सामान्य पैटर्न के अनुकूल बनाने और इसे लागू करने से लेकर विशिष्ट विवरणों तक इसे लागू करने का लक्ष्य है।
इवान प्लाइस

1
@EvanPlaice ओके मैं समझता हूं, धन्यवाद। मुझे लगता है कि यह यहाँ भ्रमित करने वाला है क्योंकि डिपॉज़िट को संज्ञा के रूप में और एक क्रिया के रूप में सोचा जा सकता है ...
मिथिर

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

जवाबों:


13

आप अमूर्त की एक परत में जोड़ रहे हैं जो भ्रामक है

आपका एपीआई बहुत साफ और सरल शुरू होता है। एक HTTP POST दिए गए मापदंडों के साथ एक नया जमा संसाधन बनाता है। फिर आप "कार्रवाइयों" के विचार को शुरू करते हुए रेल से चले जाते हैं जो कि एपीआई के मुख्य भाग के बजाय कार्यान्वयन विवरण हैं।

एक विकल्प के रूप में इस HTTP वार्तालाप पर विचार करें ...

पोस्ट / कार्ड / {कार्ड-आईडी} / खाता / {खाता-आईडी} / जमा

AmountToDeposit = 100, विभिन्न पैरामीटर ...

201 बनाया गया

स्थान = / कार्ड / 123 / खाता / 456 / जमा / 789

अब आप इस ऑपरेशन को पूर्ववत करना चाहते हैं (तकनीकी रूप से इसे संतुलित लेखा प्रणाली में अनुमति नहीं दी जानी चाहिए लेकिन क्या है):

DELETE / कार्ड / 123 / खाता / 456 / जमा / 789

204 सं

एपीआई उपभोक्ता जानता है कि वे एक डिपॉजिट संसाधन के साथ काम कर रहे हैं और यह निर्धारित करने में सक्षम है कि इस पर कौन से संचालन की अनुमति है (आमतौर पर HTTP में विकल्प के माध्यम से)।

हालाँकि, डिलीट ऑपरेशन का कार्यान्वयन आज "एक्शन" के माध्यम से किया जाता है, लेकिन इस बात की कोई गारंटी नहीं है कि जब आप इस सिस्टम से माइग्रेट करते हैं, तो C # से हास्केल तक और सामने वाले छोर को बनाए रखें कि "एक्शन" का सेकेंडरी कॉन्सेप्ट वैल्यू एड करता रहे , जबकि डिपॉजिट की प्राथमिक अवधारणा निश्चित रूप से है।

DELETE और डिपॉजिट के विकल्प को कवर करने के लिए संपादित करें

डिलीट ऑपरेशन से बचने के लिए, लेकिन फिर भी प्रभावी रूप से डिपॉजिट को हटा दें आपको निम्नलिखित कार्य करने चाहिए (डिपॉजिट और विदड्रॉल की अनुमति के लिए एक सामान्य लेनदेन का उपयोग करते हुए):

पोस्ट / कार्ड / {कार्ड-आईडी} / खाता / {खाता-आईडी} / लेन-देन

राशि = -100 , विभिन्न पैरामीटर ...

201 बनाया गया

स्थान = / कार्ड / 123 / खाता / 456 / लेन-देन / 790

एक नया लेन-देन संसाधन बनाया जाता है, जिसमें बिलकुल विपरीत राशि (-100) होती है। इसमें मूल लेन-देन को नकारते हुए खाते को 0 पर वापस संतुलित करने का प्रभाव है।

आप जैसे "उपयोगिता" समापन बिंदु बनाने पर विचार कर सकते हैं

POST / कार्ड / {कार्ड-आईडी} / खाता / {खाता-आईडी} / लेन-देन / 789 / पूर्ववत करें - BAD!

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


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

इसलिए, यदि मैं अपने प्रश्नों में, डिलीट / एक्शन / के बजाय डिलीट / डिपॉजिट / ... को ठीक करूं तो क्या यह ठीक है?
मिथिर

2
@ मिथिर मैं लेखा नियम का वर्णन कर रहा था। एक मानक डबल-एंट्री बहीखाता पद्धति में आप कभी भी लेनदेन को नहीं हटाते हैं। इतिहास एक बार प्रतिबद्ध लोगों को ईमानदार रखने के लिए अपरिवर्तनीय माना जाता है। आपके मामले में आप अभी भी एक DELETE कार्रवाई का उपयोग कर सकते हैं, लेकिन बैक-एंड (पूर्व सामान्य लेज़र डेटाबेस तालिका) पर आप उपयोगकर्ता को पैसे वापस करने (यानी वापस देने) का प्रतिनिधित्व करने वाला एक और लेनदेन जोड़ सकते हैं। मैं कोई बीन काउंटर (यानी अकाउंटेंट) नहीं हूं, लेकिन यह एक मानक प्रथाओं में से एक है जो "सिद्धांतों के लेखांकन I" पाठ्यक्रम में पढ़ाया जाता है।
इवान प्लाइस

2
(cont) डेटाबेस लॉग एक समान तरीके से लेनदेन का उपयोग करते हैं। इसलिए केवल लॉग का उपयोग करके किसी डेटासेट को फिर से बनाना और / या पुनर्निर्माण करना संभव है। जब तक लेन-देन कालानुक्रमिक रूप से फिर से नहीं किया जाता है, तब तक इसके इतिहास में किसी भी बिंदु से डेटासेट का पुनर्निर्माण संभव होना चाहिए। समीकरण से उत्परिवर्तन को हटाकर स्थिरता सुनिश्चित करता है।
इवान प्लाइस

1
काफी हद तक सिर्फ लेन-देन का नाम बदलकर।
गैरी रोवे

1

REST अस्तित्व का मुख्य कारण नेटवर्क त्रुटियों के खिलाफ लचीलापन है। जिसे समाप्त करने के लिए सभी कार्यों को निष्प्रभावी होना चाहिए ।

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

PUT /card/{card-id}/account/{account-id}/Deposit/{action-id}
AmountToDeposit=100, different parameters...

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

यह PUT का उपयोग करने के लिए अधिक समझ में आता है, क्योंकि यह सिर्फ संसाधन लिखता है और बेरोजगार है, लेकिन POST का उपयोग करने से वास्तव में कोई समस्या नहीं होगी।

लेन-देन के विवरण को देखने के लिए ग्राहक का GETएक ही यूआरएल होगा, अर्थात

GET /card/{card-id}/account/{account-id}/Deposit/{action-id}

और इसे पूर्ववत करने के लिए, यह इसे हटा सकता है। लेकिन अगर इसका वास्तव में पैसे से कोई लेना-देना नहीं है, जैसा कि नमूना बताता है, तो मैं जवाबदेही के लिए इसके बजाय जोड़े गए "रद्द" झंडे के साथ इसे इंगित करने का सुझाव दूंगा (क्योंकि इसमें बनाए गए और रद्द किए गए लेनदेन का पता चलता है)।

अब आपको विशिष्ट आईडी बनाने की एक विधि चुनने की आवश्यकता है। आपके पास कई विकल्प हैं:

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

2
मुझे जो पता है, उससे POST नहीं है। en.wikipedia.org/wiki/POST_(HTTP)#Affecting_server_state
मिथिर

@ मिथिर: POST को बेकार नहीं माना जाता है; यह अभी भी हो सकता है। लेकिन यह सच है कि चूंकि REST के सभी कार्य निष्प्रभावी होने चाहिए, इसलिए POST का मूल रूप से REST में कोई स्थान नहीं है।
Jan Hudec

1
मैं भ्रमित हूं ... जिस सामग्री को मैंने पढ़ा है और मौजूदा क्रियान्वयन से परिचित हूं (ServiceStack, ASP.NET वेब एपीआई), सभी का सुझाव है कि POST का REST में एक स्थान है।
मिथिर २३'१३ रात

3
REST में बेरोजगारी को संसाधन को सौंपा गया है, न कि प्रोटोकॉल या इसके प्रतिक्रिया कोड को। इस प्रकार, HTTP पर RET में GET, PUT, DELETE, PATCH इत्यादि के तरीकों पर विचार किया जाता है, हालांकि उनके अनुक्रिया कोड बाद की कॉल के लिए भिन्न हो सकते हैं। POST इस मायने में उदासीन है कि हर कॉल एक नया संसाधन बनाता है। देखें फील्डिंग POST का उपयोग करना ठीक है
गैरी रोवे

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