बिना क्रिया के REST URL कैसे बनायें?


283

मैं यह निर्धारित करने के लिए संघर्ष कर रहा हूं कि आराम करने वाले URL को कैसे डिज़ाइन किया जाए। मैं संज्ञाओं के साथ URL का उपयोग करने के बाकी दृष्टिकोण के लिए हूं और क्रियाओं को नहीं समझता कि यह कैसे करना है।

हम वित्तीय कैलकुलेटर को लागू करने के लिए एक सेवा का निर्माण कर रहे हैं। कैलकुलेटर मापदंडों का एक गुच्छा लेता है जिसे हम CSV फ़ाइल के माध्यम से अपलोड करेंगे। उपयोग के मामलों में शामिल होंगे:

  1. नए पैरामीटर अपलोड करें
  2. नवीनतम पैरामीटर प्राप्त करें
  3. किसी दिए गए व्यवसाय की तारीख के लिए पैरामीटर प्राप्त करें
  4. मापदंडों का एक सेट सक्रिय करें
  5. मापदंडों का एक सेट मान्य करें

मुझे लगता है कि बाकी प्रकार के URL होने के लिए मैं शेष दृष्टिकोण इकट्ठा करूंगा:

/parameters
/parameters/12-23-2009

आप पहले तीन उपयोग मामलों को प्राप्त कर सकते हैं:

  1. POST जहाँ आप पोस्ट अनुरोध में पैरामीटर फ़ाइल शामिल करते हैं
  2. पहले URL का GET
  3. दूसरे URL का GET

लेकिन आप क्रिया के बिना 4 वें और 5 वें उपयोग के मामले को कैसे करते हैं? क्या आपको URL की आवश्यकता नहीं होगी:

/parameters/ID/activate
/parameters/ID/validate

??


3
आंशिक अपडेट के लिए मैं POST के बजाय PATCH को पसंद करता हूं।
user2016971

जवाबों:


71

शायद कुछ इस तरह:

PUT /parameters/activation HTTP/1.1
Content-Type: application/json; encoding=UTF-8
Content-Length: 18

{ "active": true }

1
POSTयदि आपको अनुरोध भेजने पर हर बार मापदंडों को सत्यापित करने की तरह "प्रक्रिया" करने की आवश्यकता हो तो ठीक है। लेकिन जब आप संसाधन की स्थिति (अनुप्रयोग) को संशोधित करते हैं, तो आप वास्तव में मौजूदा संसाधन को अपडेट करते हैं, कुछ नए संसाधन नहीं बनाते हैं या प्रोसेसिंग अनुरोध पोस्ट नहीं करते हैं।
एंड्री वाल्स्सोविच शेख

19
PUT एक नया संसाधन बनाने के लिए है, या किसी विशेष URL पर एक नया संसाधन रखकर (संपूर्ण रूप से, भाग में नहीं)। मैं यह नहीं देखता कि PUT इस मामले में कैसे फिट बैठता है।
ब्रेटन

30
वास्तव में, POSTबनाम PUTवास्तव में की तरह नहीं है insertबनाम updatePUTदिए गए पथ के अनुरूप संसाधन को अद्यतन करता है, या दिए गए पथ के अनुरूप एक नया संसाधन बनाता है। POSTकहीं नया संसाधन बनाता है। उदाहरण के लिए, PUT /blog/posts/3/comments/5उपयुक्त टिप्पणी को अद्यतन करेगा, जबकि POST /blog/posts/3/commentsएक नया commentसंसाधन बनाएगा (और प्रतिक्रिया में नए संसाधन के लिए पथ को वापस करना चाहिए)।
yfeldblum

23
@Justice @Breton अधिक महत्वपूर्ण अंतर यह है कि PUTजब तक POSTयह नहीं होता है तब तक यह बहुत ही सुखद होता है । आमतौर पर आपको जितना संभव हो उतना परिणाम प्रदान करने में बाधाएं डालनी चाहिए। साथ चिपके PUTरहना सेवा के ग्राहक को अधिक जानकारी देता है।
एंड्रे व्लास्लोविच शेख

3
संसाधन भी / पैरामीटर / स्थिति हो सकते थे और अनुरोध का मुख्य भाग "सक्रिय" हो सकता था। इस तरह आप किसी विशेष URL पर किसी नए संसाधन को रख रहे हैं।
कार्लोस अगुआयो

991

अच्छे यूआरआई डिजाइन के लिए सामान्य सिद्धांत:

  • राज्य को बदलने के लिए क्वेरी मापदंडों का उपयोग करें
  • यदि आप इसे मदद कर सकते हैं तो मिश्रित-केस पथ का उपयोग करें; लोअरकेस सबसे अच्छा है
  • अपने यूआरआई (.php, .py, .pl, आदि) में कार्यान्वयन-विशिष्ट एक्सटेंशन का उपयोग करें।
  • अपने URI के साथ RPC में पड़ें
  • करो संभव के रूप में ज्यादा के रूप में अपने यूआरआइ अंतरिक्ष की सीमा
  • Do रखें पथ के सेगमेंट कम
  • Do या तो पसंद करते हैं /resourceया /resource/; जो आप उपयोग नहीं करते हैं उससे 301 रीडायरेक्ट बनाएं
  • संसाधन के उप-चयन के लिए क्वेरी पैरामीटर का उपयोग करें ; यानी पेजिनेशन, सर्च क्वेश्चन
  • क्या चाल सामान यूआरआई से बाहर है कि एक HTTP शीर्ष लेख या एक शरीर में होना चाहिए

(ध्यान दें: मैंने "रैस्टफुल यूआरआई डिज़ाइन" नहीं कहा था; यूआरआई अनिवार्य रूप से रीरेस्ट में अपारदर्शी हैं)

HTTP विधि पसंद के लिए सामान्य सिद्धांत:

  • राज्य को बदलने के लिए कभी भी GET का उपयोग करें; यह Googlebot का आपका दिन बर्बाद करने का एक शानदार तरीका है
  • जब तक आप संपूर्ण संसाधन अपडेट नहीं कर रहे हैं, तब तक PUT का उपयोग करें
  • जब तक आप वैध रूप से उसी URI पर GET नहीं कर सकते, तब तक PUT का उपयोग करें
  • लंबे समय तक रहने वाली जानकारी को पुनर्प्राप्त करने के लिए POST का उपयोग करें या जो कैश के लिए उचित हो सकता है
  • ऐसा ऑपरेशन न करें जो PUT के साथ सुस्पष्ट न हो
  • क्या जितना संभव हो उतना के लिए उपयोग प्राप्त
  • संदेह होने पर PUT को वरीयता में POST का उपयोग करें
  • जब भी आपको ऐसा कुछ करना हो, जो RPC की तरह महसूस हो तो POST का उपयोग करें
  • क्या है कि बड़े या श्रेणीबद्ध हैं संसाधनों की कक्षाओं के लिए उपयोग PUT
  • संसाधनों को हटाने के लिए POST को प्राथमिकता में DELETE का उपयोग करें
  • Do गणना जैसी चीजों के लिए उपयोग मिलता है, जब तक कि आपके इनपुट बड़ी है, जो मामले उपयोग पोस्ट में

HTTP के साथ वेब सेवा डिजाइन के सामान्य सिद्धांत:

  • एक प्रतिक्रिया के शरीर में मेटाडेटा मत रखो जो हेडर में होना चाहिए
  • मत करो एक अलग संसाधन में मेटाडाटा डाल जब तक सहित यह महत्वपूर्ण ओवरहेड बन जाएगा
  • करो उचित स्थिति कोड का उपयोग
    • 201 Createdसंसाधन बनाने के बाद; प्रतिक्रिया भेजे जाने के समय संसाधन मौजूद होना चाहिए
    • 202 Accepted किसी ऑपरेशन को सफलतापूर्वक करने के बाद या असिंक्रोनस रूप से संसाधन बनाना
    • 400 Bad Requestजब कोई व्यक्ति डेटा पर एक ऑपरेशन करता है जो स्पष्ट रूप से फर्जी है; आपके आवेदन के लिए यह एक सत्यापन त्रुटि हो सकती है; आम तौर पर अनियोजित अपवादों के लिए 500 आरक्षित
    • 401 Unauthorizedजब कोई आपके एपीआई को आवश्यक Authorizationशीर्षकों की आपूर्ति के बिना या जब Authorizationअमान्य हैं तो क्रेडेंशियल्स के बिना एक्सेस करता है ; यदि आप Authorizationहेडर के माध्यम से क्रेडेंशियल्स की उम्मीद नहीं कर रहे हैं तो इस प्रतिक्रिया कोड का उपयोग न करें ।
    • 403 Forbidden जब कोई आपके एपीआई को इस तरह से एक्सेस करता है जो दुर्भावनापूर्ण हो सकता है या यदि वे अधिकृत नहीं हैं
    • 405 Method Not Allowed जब कोई POST का उपयोग करता है जब उन्हें PUT, आदि का उपयोग करना चाहिए था
    • 413 Request Entity Too Large जब कोई आपको अस्वीकार्य रूप से बड़ी फ़ाइल भेजने का प्रयास करता है
    • 418 I'm a teapot जब एक चायदानी के साथ कॉफी काढ़ा करने का प्रयास
  • जब भी आप कर सकते हैं कैशिंग हेडर का उपयोग करें
    • ETag हेडर अच्छे हैं जब आप किसी संसाधन को हैश मान में आसानी से कम कर सकते हैं
    • Last-Modified आपको संकेत देना चाहिए कि संसाधनों के अद्यतन होने के समय को ध्यान में रखते हुए एक अच्छा विचार है
    • Cache-Controlऔर Expiresसमझदार मूल्यों को दिया जाना चाहिए
  • क्या एक अनुरोध में हेडर कैशिंग सम्मानित करने के लिए सब कुछ आप कर सकते हैं ( If-None-Modified, If-Modified-Since)
  • जब वे समझ में आते हैं तो पुनर्निर्देश का उपयोग करें , लेकिन ये एक वेब सेवा के लिए दुर्लभ होना चाहिए

आपके विशिष्ट प्रश्न के संबंध में, POST का उपयोग # 4 और # 5 के लिए किया जाना चाहिए। ये ऑपरेशन ऊपर दिए गए "RPC- जैसे" दिशानिर्देश के तहत आते हैं। # 5 के लिए, याद रखें कि POST का उपयोग करना आवश्यक नहीं है Content-Type: application/x-www-form-urlencoded। यह आसानी से JSON या CSV पेलोड हो सकता है।


11
413 आपके द्वारा भेजे जा रहे अनुरोध के आकार के लिए अभिप्रेत है ताकि आप विनम्रतापूर्वक किसी को आपको डेटा भेजने के लिए अस्वीकार कर सकें, अक्सर 411 के साथ संयोजन के रूप में ताकि आप लोगों को यह बताने के लिए मजबूर करें कि आपको कितना भेजा जा रहा है। 413 के खिलाफ दिए गए उदाहरण के लिए, मुझे लगता है कि 400 अधिक उचित प्रतिक्रिया होगी।
गैरी शॉटलर

5
+1 क्योंकि यह एक महान संसाधन है। हालाँकि, यह एक सामान्य संसाधन है और सीधे तौर पर इस सवाल का जवाब नहीं देता है। इस आदर्श में एक विशिष्ट उत्तर के साथ एक अतिरिक्त पैराग्राफ शामिल होना चाहिए।
शमूएल नेफ

@GarryShutler अच्छा पकड़, आप बिल्कुल सही कह रहे हैं। संपादन के लिए धन्यवाद।
बॉब अमन

1
हां, आप उन मामलों में केवल PUT का उपयोग करेंगे जहां आप पूरी वस्तु को अधिलेखित कर रहे हैं। हालाँकि, मेरा दावा है कि संसाधन के आंशिक अद्यतन के मामले में PATCH या POST उचित हैं। ऑपरेशन क्या करने जा रहा है, इस संदर्भ में PATCH अधिक स्पष्ट है, लेकिन क्योंकि सभी ग्राहक PATCH अनुरोध जारी करने में सक्षम नहीं हैं, इसलिए इसके बजाय POST की अनुमति देना पूरी तरह से उचित है , और मैं वकालत करने के लिए इतनी दूर भी जा सकता हूं कि यदि PATCH का उपयोग किया जाता है तो POST को हमेशा गिरावट की अनुमति दी जानी चाहिए ।
बॉब अमन

1
409 त्रुटियों के लिए +1। 400 त्रुटि एक ऐसी चीज है जिसे पर्याप्त ग्राहक-पक्ष सत्यापन द्वारा हल किया जा सकता है। एक 409 स्पष्ट करता है कि अनुरोध स्वयं स्वीकार्य और सुसंगत था, लेकिन सर्वर स्थिति के कुछ पहलू (आमतौर पर संगामिति नियंत्रण, लेकिन सैद्धांतिक रूप से किसी भी गैर-इनपुट बाधा) के साथ संघर्ष करता है।
क्लेटनटांड

18

जब भी ऐसा लगे कि आपको एक नई क्रिया की आवश्यकता है, तो उस क्रिया को बदले में संज्ञा में बदलने के बारे में सोचें। उदाहरण के लिए, 'सक्रियण' को 'सक्रियण', और 'सत्यापन' को 'सत्यापन' में बदल दें।

लेकिन अभी आपने जो लिखा है उससे मैं कहूंगा कि आपके आवेदन में बहुत बड़ी समस्याएं हैं।

किसी भी समय 'पैरामीटर' नामक एक संसाधन प्रस्तावित है, इसे परियोजना के प्रत्येक सदस्य के दिमाग में लाल झंडे भेजना चाहिए। 'पैरामीटर' वस्तुतः किसी भी संसाधन पर लागू हो सकता है; यह पर्याप्त विशिष्ट नहीं है।

'पैरामीटर' वास्तव में क्या दर्शाता है? संभवतः कई अलग-अलग चीजें, जिनमें से प्रत्येक के पास इसके लिए एक अलग संसाधन होना चाहिए।

इसे प्राप्त करने का एक और तरीका है - जब आप अंतिम उपयोगकर्ताओं के साथ अपने आवेदन पर चर्चा करते हैं (जो संभवतः प्रोग्रामिंग के बारे में बहुत कम जानते हैं) वे शब्द क्या हैं जो वे स्वयं बार-बार उपयोग करते हैं?

वे शब्द हैं जिन्हें आपको अपने एप्लिकेशन को डिज़ाइन करना चाहिए।

यदि आपके पास अभी तक भावी उपयोगकर्ताओं के साथ यह रूपांतरण नहीं हुआ है - अभी सब कुछ रोक दें और जब तक आप ऐसा न करें कोड की दूसरी पंक्ति न लिखें! इसके बाद ही आपकी टीम को इस बात का अंदाजा होगा कि किन चीजों को बनाने की जरूरत है।

मुझे वित्तीय सॉफ़्टवेयर के बारे में कुछ नहीं पता है, लेकिन अगर मुझे अनुमान लगाना था, तो मैं कहूंगा कि कुछ संसाधन "रिपोर्ट", "भुगतान", "स्थानांतरण" और "मुद्रा" जैसे नामों से जा सकते हैं।

सॉफ्टवेयर डिजाइन प्रक्रिया के इस हिस्से पर कई अच्छी किताबें हैं। दो मैं सिफारिश कर सकता हूँ डोमेन संचालित डिजाइन और विश्लेषण पैटर्न हैं


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

1
कभी-कभी मुझे शब्दों को "संसाधन" जैसे "सक्रियकर्ता" या "सत्यापनकर्ता" में परिवर्तित करना उपयोगी लगता है। RFC 2616 के अनुसार POST का उपयोग "डेटा का एक ब्लॉक प्रदान करने ... डेटा से निपटने की प्रक्रिया के लिए" के लिए किया जा सकता है
डारेल मिलर

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

@ मारकस - यह एक बहुत ही असामान्य मामले की तरह लगता है। शायद अगर आपने बताया कि आपका ऐप और अधिक विस्तार से क्या करता है, तो हम संसाधनों की पहचान करने के लिए बेहतर सुझाव दे पाएंगे।
रिच एपोडाका

1
"जब आप अंतिम उपयोगकर्ताओं के साथ अपने आवेदन पर चर्चा करते हैं तो वे शब्द क्या होते हैं जो वे स्वयं बार-बार उपयोग करते हैं?" ... और क्या होगा अगर वे सभी क्रिया हैं? XD
अमलगोविनस

11

आपके URL के डिज़ाइन का इस बात से कोई लेना-देना नहीं है कि आपका एप्लिकेशन Restful है या नहीं। वाक्यांश "RESTful URL" इसलिए बकवास है।

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

उस ने कहा, चलो अपने प्रश्न के लिए जाओ: पिछले दो मामले रेस्टफुल नहीं हैं और किसी भी प्रकार की बाकी योजना में फिट नहीं होते हैं। जिन्हें आप RPC कह सकते हैं। यदि आप REST के बारे में गंभीर हैं, तो आपको इस बात पर पुनर्विचार करना होगा कि आपका आवेदन जमीन से कैसे काम करता है। या तो REST का त्याग करें या RPC ऐप के रूप में अपना ऐप करें।

शायद नहीं।

यहां विचार यह है कि आपको एक संसाधन के रूप में सब कुछ व्यवहार करना होगा, इसलिए एक बार मापदंडों के एक सेट में एक URL होता है जिसे आप इसमें से संदर्भित कर सकते हैं, जिसे आप जोड़ते हैं:

GET [parametersurl]/validationresults

POST [paramatersurl]
body: {command:"activate"}

लेकिन फिर, वह सक्रिय चीज़ RPC है, REST नहीं।


आप यहाँ एक दिलचस्प बात बताते हैं। क्या आप थोड़ा और विस्तृत कर सकते हैं कि इस तरह की चीज़ों के लिए Restful दृष्टिकोण कैसे होगा?
poezn

मैंने यहाँ प्रतिक्रियाओं को पढ़ने में थोड़ा समय बिताया है, और मुझे लगता है कि न्याय कुछ हो सकता है। वह आपके मापदंडों के व्यक्तिगत गुणों को व्यक्तिगत संसाधनों के रूप में मॉडल करता है, और उस संसाधन पर उस संपत्ति की सामग्री को बदलने के लिए PUT क्रिया का उपयोग करता है। यह संसाधनों के संग्रह के रूप में प्रत्येक वस्तु की स्थिति को मॉडलिंग कर रहा है, और संसाधन को रखने या हटाने या संशोधित करने के रूप में राज्य को संशोधित कर रहा है। सत्यापन के लिए- आपको केवल एक संसाधन की आवश्यकता है जो जादुई रूप से बताता है कि पैरामीटर मान्य हैं या नहीं, जैसा कि मेरे उत्तर में ऊपर है। यह तब तक ठीक रहेगा, जब तक इसका कोई दुष्प्रभाव न हो।
ब्रेटन

बशर्ते, "सक्रिय" जो करता है वह केवल एक संपत्ति को सच करने के लिए निर्धारित है। अगर इसे कुछ और करना है, तो यह अभी भी Restful नहीं है, और मुझे यकीन नहीं है कि आप इसे RESTfully कैसे मॉडल करेंगे।
ब्रेटन

मुझे नहीं लगता कि आप कह सकते हैं कि पिछले दो मामले रेस्टफुल नहीं हैं। सक्रिय रूप से सक्रिय और मान्य कहने के अप्रत्यक्ष तरीके हैं कि संसाधन एक राज्य मशीन में नए राज्य में बदल रहा है। REST इसे मॉडलिंग करने में काफी सक्षम है।
डारेल मिलर

@ विवाद, मुझे लगता है कि आप REST का एक हिस्सा इंगित करते हैं जो कई लोगों के लिए चुनौतीपूर्ण हो सकता है जो REST के लिए नए हैं। आप "संसाधन संसाधन x" ऑपरेशन को लागू करने के बारे में कैसे जा सकते हैं? मुझे लगता है कि चुनौतीपूर्ण बात यह है कि यह एक ऑपरेशन है जिसके परिणामस्वरूप राज्य में बदलाव हो सकता है, लेकिन नया राज्य अनुरोध किए जाने का एक परिणाम है।
सीन

6

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

उदा। कुछ संसाधन बनाएं जैसे,

/ActiveParameters
/ValidatedParameters

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

POST /ActiveParameters?parameter=/Parameters/{Id}

एक ही चीज़ को / ValidatedParameters के साथ किया जा सकता है। यदि पैरामीटर मान्य नहीं हैं, तो सर्वर मान्य पैरामीटर के संग्रह में पैरामीटर जोड़ने के अनुरोध पर "खराब अनुरोध" वापस कर सकता है।


1

मैं निम्नलिखित मेटा संसाधन और विधियों का सुझाव दूंगा।

पैरामीटर सक्रिय करें और / या उन्हें मान्य करें:

> PUT /parameters/<id>/meta HTTP/1.1
> Host: example.com
> Content-Type: application/json
> Connection: close
>
> {'active': true, 'require-valid': true}
>
< HTTP/1.1 200 OK
< Connection: close
<

जाँचें कि क्या पैरामीटर सक्रिय और मान्य हैं:

> GET /parameters/<id>/meta HTTP/1.1
> Host: example.com
> Connection: close
>
< HTTP/1.1 200 OK
< Content-Type: application/json
< Connection: close
<
< {
<     'active': true,
<     'require-valid': true,
<     'valid': {'status': false, 'reason': '...'}
< }
<

जहाँ तक मैं समझता हूँ, प्रश्न बाकी URL के नामकरण के बारे में है, कार्यक्षमता के बारे में नहीं है, है ना?
21

2
"रेस्टफुल यूआरएल" तक सीमित एक प्रश्न एक बुरा सवाल है और इसका जवाब नहीं दिया जाना चाहिए। इसके बजाय "संबंधित संसाधनों और URL के साथ प्रतिष्ठित संसाधन" पर विचार करने के लिए प्रश्न का विस्तार किया जाना चाहिए, और इस तरह का उत्तर दिया जाना चाहिए।
yfeldblum

जैसा कि मैंने इसे समझा, यह सवाल URL नामकरण परंपराओं के बारे में था और HTTP विधियों नाम संसाधन का जवाब देना चाहिए।
एंड्री वाल्स्सोविच शेख

1

मुझे यह देखकर थोड़ा दुख होता है कि 10 साल से अधिक समय के बाद वास्तव में यह बताने का कोई जवाब नहीं है कि ओपी में अनुरोध की गई चीज को REST आर्किटेक्चर में कैसे डिजाइन किया जा सकता है, इसलिए मुझे अब ऐसा करने की आवश्यकता है।

पहली चीजें पहले, क्या है? संक्षिप्त REST या ReST का अर्थ "प्रतिनिधि राज्य स्थानांतरण" है और एक निश्चित प्रतिनिधित्व प्रारूप में संसाधन की स्थिति के आदान-प्रदान को परिभाषित करता है। प्रतिनिधित्व प्रारूप बातचीत की मीडिया प्रकार के लिए ज्वार है। application/htmlप्रतिनिधित्व प्रारूप के मामले में , HTML स्वरूपित पाठ सामग्री की एक धारा हो सकती है जो ब्राउज़र में प्रदान की जाती है, शायद कुछ स्थानों पर कुछ तत्वों की स्थिति के लिए कुछ स्टाइलशीट फ़ॉर्मेटिंग लागू करने के बाद।

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

एक वेब आधारित कैलकुलेटर आमतौर पर कुछ "पेज" से शुरू हो सकता है जो आपको सर्वर में प्रवेश किए गए डेटा भेजने से पहले गणना करने के लिए कुछ मान इनपुट करने की अनुमति देता है। HTML में यह आमतौर पर HTML <form>तत्वों के माध्यम से प्राप्त किया जाता है जो सेट करने के लिए उपलब्ध मापदंडों पर एक ग्राहक को सिखाता है, इनपुट डेटा भेजने पर आवेदन करने के लिए अनुरोध के साथ ही प्रतिनिधित्व प्रारूप भेजने के लिए लक्ष्य स्थान। यह इस तरह दिख सकता है:

<html>
  <head>
    ...
  </head>
  <body>
    <form action="/../someResource" method="post" enctype="application/x-www-form-urlencoded">
      <label for="firstNumber">First number:</label>
      <input type="number" id="firstNumber" name="firstNumber"/>

      <label for="secondNumber">Second number:</label>
      <input type="number" id="secondNumber" name="secondNumber"/>

      <input type="submit" value="Add numbers"/>
    </form>
  </body>
</html>

ऊपर दिए गए नमूने में कहा गया है कि दो इनपुट फ़ील्ड हैं जिन्हें उपयोगकर्ता या किसी अन्य ऑटोमेटा द्वारा भरा जा सकता है, और सबमिट इनपुट तत्व को आमंत्रित करने पर ब्राउज़र इनपुट डेटा को एक application/x-www-form-urlencodedप्रतिनिधित्व प्रारूप में भेजने का ध्यान रखता है जो भेजा जाता है POSTइस मामले में निर्दिष्ट HTTP अनुरोध विधि के माध्यम से उल्लिखित लक्ष्य स्थान पर । अगर हम में प्रवेश 1में firstNumberइनपुट क्षेत्र और 2में secondNumberइनपुट क्षेत्र, ब्राउज़र का प्रतिनिधित्व उत्पन्न होगा firstNumber=1&secondNumber=2और लक्ष्य संसाधन के लिए वास्तविक अनुरोध के शरीर पेलोड के रूप में इस भेजें।

सर्वर को जारी किया गया कच्चा HTTP अनुरोध इस तरह दिख सकता है:

POST /../someResource
Host: www.acme.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 28
Accept: application/html

firstNumber=1&secondNumber=2

सर्वर गणना का प्रदर्शन कर सकता है और एक और HTML पृष्ठ के साथ प्रतिक्रिया कर सकता है जिसमें गणना का परिणाम होता है, क्योंकि अनुरोध ने संकेत दिया कि ग्राहक इस प्रारूप को समझता है।

जैसा कि ब्रेटन ने पहले ही बताया कि "रेस्टफुल" URL या URI जैसी कोई चीज नहीं है। एक यूआरआई / यूआरएल अपनी तरह की चीज है और इसे किसी ग्राहक / उपयोगकर्ता को नहीं देना चाहिए। किसी उपयोगकर्ता के ऊपर कैलकुलेटर के नमूने में बस यह दिलचस्पी नहीं है कि उसे डेटा कहां भेजा जाए, बस इसमें रुचि है कि सबमिट इनपुट फ़ील्ड को ट्रिगर करने पर अनुरोध भेजा जाता है। कार्य करने के लिए आवश्यक सभी आवश्यक जानकारी पहले से ही सर्वर द्वारा दी जानी चाहिए।

एक ब्राउज़र को इस बात की भी जानकारी नहीं हो सकती है कि अनुरोध वास्तव में कुछ इनपुट मापदंडों के साथ एक कैलकुलेटर खिला रहा है, यह किसी प्रकार का एक ऑर्डर फॉर्म हो सकता है जो आदेश देने की प्रक्रिया को जारी रखने के लिए बस अगले फॉर्म का प्रतिनिधित्व करता है या कुछ बिल्कुल अलग तरह का संसाधन। यह बस ऐसे मामले में HTML कल्पना की मांग करता है और यह कम परवाह नहीं कर सकता है कि सर्वर वास्तव में क्या कर रहा है। यह अवधारणा एक ब्राउज़र को एक ही प्रतिनिधित्व प्रारूप का उपयोग करने में सक्षम बनाती है, जैसे कि आपकी पसंदीदा ऑनलाइन दुकान से कुछ सामान ऑर्डर करने, अपने सबसे अच्छे दोस्तों के साथ चैट करने, ऑनलाइन खाते में प्रवेश करने आदि।

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

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

दुर्भाग्य से तथाकथित "REST" एपीआई वास्तव में सब कुछ है लेकिन ऐसा है। आप ज्यादातर JSON आधारित डेटा के आदान-प्रदान को देखते हैं जो कि एपीआई विशिष्ट बाहरी दस्तावेज में निर्दिष्ट होता है जो आमतौर पर फ्लाई पर गतिशील रूप से एकीकृत करने के लिए कठिन होता है। प्रारूप जिसे देखने के लिए अनुरोध की आवश्यकता होती है, बाहरी दस्तावेज में भी हार्डकोड किया गया है, जो पूर्ववर्ती प्रकारों को वापस करने के लिए यूआरआई की व्याख्या करने के लिए बहुत सारे कार्यान्वयन की ओर ले जाता हैइसके बजाय कुछ सामान्य प्रतिनिधित्व प्रारूप का उपयोग किया जाता है, जो कि अग्रिम बातचीत की जाती है। यह सर्वरों को बदलने से रोकता है क्योंकि ग्राहक अब एक निश्चित डेटा प्रारूप प्राप्त करने की उम्मीद करते हैं (पूर्वनिर्धारित यूआरआई के लिए प्रतिनिधित्व प्रारूप नहीं!)। यह कस्टम डेटा प्रारूप विनिमय इसके अलावा ग्राहकों को अन्य एपीआई के साथ बातचीत करने से रोकता है क्योंकि "डेटा प्रारूप" आमतौर पर एक विशिष्ट एपीआई के लिए ज्वार होता है। हम इस अवधारणा को अतीत से कोरबा, आरएमआई या एसओएपी जैसी प्रौद्योगिकियों से जानते हैं, जिन्हें हम किसी भी तरह से बुराई के रूप में निंदा करते हैं, हालांकि पेपॉल ने एएस 2 को एएस 4 के साथ हाल ही में डिफ़ॉल्ट ट्रांसफर प्रोटोकॉल के रूप में बदलकर इसे फिर से स्थानांतरित कर दिया।

पूछे गए वास्तविक प्रश्न के संबंध में, सीएसवी फ़ाइल के रूप में डेटा भेजना application/x-www-form-urlencodedप्रतिनिधित्व या इसी तरह के सामान का उपयोग करने से अलग नहीं है। जिम वेबर ने स्पष्ट किया कि आखिरकार HTTP एक ट्रांसपोर्ट प्रोटोकॉल है जिसका एप्लिकेशन डोमेन वेब पर दस्तावेजों का हस्तांतरण है । क्लाइंट और सर्वर को कम से कम दोनों समर्थन RFC 7111text/csv में परिभाषित होने चाहिए । यह CSV फ़ाइल एक मीडिया प्रकार के प्रसंस्करण के परिणाम के रूप में उत्पन्न हो सकती है जो फॉर्म एलिमेंट्स, एक लक्ष्य तत्व या विशेषता के साथ-साथ कॉन्फ़िगरेशन को अपलोड करने के लिए HTTP विधि के साथ-साथ अनुरोध भेजने के लिए उत्पन्न होती है।

कुछ प्रकार के मीडिया प्रकार हैं जो HTML , HAL फॉर्म्स , हैलफॉर्म , आयन या हाइड्रा जैसे रूपों का समर्थन करते हैं । मैं वर्तमान में, हालांकि, एक मीडिया प्रकार के बारे में नहीं जानता जो स्वचालित रूप से इनपुट डेटा को text/csvसीधे सांकेतिक शब्दों में बदलना कर सकता है इसलिए किसी को IANA के मीडिया प्रकार की रजिस्ट्री के साथ परिभाषित और पंजीकृत करने की आवश्यकता हो सकती है ।

पूर्ण पैरामीटर सेट का अपलोड और डाउनलोड मुझे लगता है कि एक मुद्दा नहीं होना चाहिए। जैसा कि पहले उल्लेख किया गया है, लक्ष्य URI प्रासंगिकता का नहीं है क्योंकि एक ग्राहक सिर्फ नई सामग्री को संसाधित करने के लिए URI का उपयोग करेगा। व्यावसायिक तिथि तक फ़िल्टर करना भी मुश्किल नहीं होना चाहिए। हालांकि सर्वर को ग्राहक को उन सभी संभावनाओं के साथ ग्राहक होना चाहिए जो ग्राहक बस से चुना जा सकता है। हाल के वर्षों में ग्राफकॉल और रेस्ट्क्लाइन विकसित हुए जो एक एसक्यूएल को भाषा की तरह पेश करते हैं जिसे फ़िल्टर किए गए प्रतिक्रिया प्राप्त करने के लिए एक निश्चित समापन बिंदु पर लक्षित किया जा सकता है। हालाँकि, एक वास्तविक REST अर्थ में यह REST के पीछे के विचार का उल्लंघन करता है) ग्राफ़कॉलिक यानी केवल एक एकल समापन बिंदु का उपयोग करता है जो किसी भी तरह से कैशिंग और बी के इष्टतम उपयोग को रोकता है) को उपलब्ध फ़ील्ड के ज्ञान की आवश्यकता होती है, जिससे ग्राहकों का युग्मन शुरू हो सकता है। संसाधन का आधार डेटा मॉडल।

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

HTTP परिवर्तनों को लागू करने से पहले किसी सर्वर को प्राप्त अनुरोध को मान्य करने के लिए अनुमति देता है और प्रोत्साहित करता है। के लिए डाल कल्पना कहता है:

एक मूल सर्वर SHOULD सत्यापित करता है कि PUT प्रतिनिधित्व किसी भी बाधा के अनुरूप है जो सर्वर के पास लक्षित संसाधन के लिए है जो PUT द्वारा बदला नहीं जा सकता है या नहीं बदला जाएगा। यह विशेष रूप से महत्वपूर्ण है जब GET प्रतिक्रियाओं पर मेटाडेटा प्रतिनिधित्व के मूल्यों को निर्धारित करने के लिए मूल सर्वर URI से संबंधित आंतरिक कॉन्फ़िगरेशन जानकारी का उपयोग करता है। जब कोई PUT प्रतिनिधित्व लक्ष्य संसाधन के साथ असंगत होता है, तो मूल सर्वर SHOULD या तो उन्हें सुसंगत बनाता है, प्रतिनिधित्व को परिवर्तित करके या संसाधन कॉन्फ़िगरेशन को बदलकर, या उचित त्रुटि संदेश के साथ जवाब देने के लिए पर्याप्त जानकारी देता है कि प्रतिनिधित्व अनुपयुक्त क्यों है। 409 (संघर्ष) या 415 (असमर्थित मीडिया प्रकार) स्थिति कोड सुझाए गए हैं,

उदाहरण के लिए, यदि लक्ष्य संसाधन को हमेशा "टेक्स्ट / html" के कंटेंट-टाइप के लिए कॉन्फ़िगर किया जाता है और PUT होने का प्रतिनिधित्व कंटेंट-टाइप "इमेज / जेपीईजी" का होता है, तो मूल सर्वर को इनमें से एक करना चाहिए:

ए। नए मीडिया प्रकार को प्रतिबिंबित करने के लिए लक्ष्य संसाधन को फिर से कॉन्फ़िगर करें;

ख। PUT प्रतिनिधित्व को नए संसाधन राज्य के रूप में सहेजने से पहले संसाधन के अनुरूप एक प्रारूप में बदलना; या,

सी। 415 (असमर्थित मीडिया प्रकार) प्रतिक्रिया के साथ अनुरोध को अस्वीकार करें, यह दर्शाता है कि लक्ष्य संसाधन "पाठ / html" तक सीमित है, शायद एक अलग संसाधन के लिए लिंक सहित जो नए प्रतिनिधित्व के लिए उपयुक्त लक्ष्य होगा।

HTTP वास्तव में यह परिभाषित नहीं करता है कि एक PUT विधि मूल सर्वर की स्थिति को कैसे प्रभावित करती है जो उपयोगकर्ता एजेंट अनुरोध के इरादे और मूल सर्वर प्रतिक्रिया के शब्दार्थ द्वारा व्यक्त की जा सकती है। ...

इस पोस्ट को योग करने के लिए, आपको या तो एक मौजूदा मीडिया प्रकार का उपयोग करना चाहिए जो आपको आवश्यक या समर्थित इनपुट मापदंडों के बारे में एक ग्राहक को पढ़ाने की अनुमति देता है, अनुरोध भेजने के लिए लक्ष्य स्थान, ऑपरेशन के साथ-साथ मीडिया-प्रकार का उपयोग करने के लिए। अनुरोध में स्वरूपित किया जाना है, या अपने स्वयं के एक को परिभाषित करना है जिसे आप IANA के साथ पंजीकृत करते हैं। यदि आप इनपुट को कनवर्ट करना चाहते हैं तो बाद वाला आवश्यक हो सकता हैtext/csvऔर फिर सर्वर पर CSV प्रतिनिधित्व अपलोड करें। संसाधन में परिवर्तन लागू होने से पहले सत्यापन होना चाहिए। वास्तविक यूआरआई ग्राहकों के लिए प्रासंगिकता के अलावा यह निर्धारित करने के लिए नहीं होना चाहिए कि अनुरोध कहां भेजा जाए और इस तरह से आपको स्वतंत्र रूप से चुना जा सकता है, सेवा कार्यान्वयनकर्ता। इन चरणों का पालन करने से आप किसी भी समय अपने सर्वर साइड को बदलने की स्वतंत्रता प्राप्त कर सकते हैं और यदि वे उपयोग किए गए मीडिया-प्रकारों का समर्थन करते हैं, तो ग्राहक परिणाम के रूप में नहीं टूटेंगे।


0

संपादित करें: वास्तव में यूआरआई ने GETशेष आय से अनुरोधों को रोका होगा ।


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

400 Bad Requestयदि डेटा जमा किया गया / अमान्य है, तो स्थिति कोड के साथ वापस रिपोर्ट करें और अनुरोध को पुन: सबमिट किए जाने से पहले बदल दिया जाना चाहिए ( HTTP / 1.1% स्रोत )।

यह आपके उपयोग-मामले में इसे प्रस्तुत करने के बजाय, प्रस्तुत समय पर मान्य करने पर निर्भर करता है। अन्य उत्तरों के पास उस परिदृश्य के लिए उपयुक्त समाधान हैं।


यूआरआई एक पहचानकर्ता है। किसी विशेष URL का उपयोग करने के दुष्प्रभाव नहीं होने चाहिए। कल्पना कीजिए कि एक प्रॉक्सी इसके साथ क्या करेगा।
बर्टन

2
या गूगल, उस बात के लिए। मैंने एक बार एक वेबस्टोर के बारे में एक कहानी पढ़ी थी जिसमें इस तरह की मूढ़ता के कारण उनके सभी उत्पाद Google द्वारा हटा दिए गए थे।
ब्रेटन

0

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

http://example.com/amort_cal/2009-10-20/30yrsfixed/monthly/5.00/200000

अब, मुझे नहीं पता कि आप क्या गणना कर रहे हैं, लेकिन पैरामीटर सूची की आपकी अवधारणा RESTful नहीं लगती है। जैसा कि किसी और ने कहा, आपकी आवश्यकताएं अधिक XMLRPC से अधिक हैं। यदि आप REST के लिए प्रयास कर रहे हैं, तो आपको संज्ञा की आवश्यकता है। गणना संज्ञाएं नहीं हैं, वे क्रियाएं हैं जो संज्ञा पर कार्य करती हैं। संज्ञाओं को अपने बछड़ों से बाहर निकालने के लिए आपको इसे मोड़ने की आवश्यकता है।


5
मुझे लगता है कि यहां आगे की स्लैश का उपयोग करना थोड़ा मूर्खतापूर्ण है, amort_cal के साथ क्या गलत होगा? दिनांक = 2009-10-20 और प्रकार = 30yrsfixed और अवधि = मासिक और दर = 5.0 और initialamount = 200000? जब तक यह एक संसाधन नहीं है तब तक REST परवाह नहीं करता है। URI कल्पना हालांकि परवाह करता है। आप इस तरह की योजना के साथ काम करने के लिए रिश्तेदार लिंक की कल्पना कैसे करते हैं?
ब्रेटन

आप फिर भी एक अच्छा बिंदु लाते हैं। क्या इन "मापदंडों" को भी सर्वराइड संग्रहीत करने की आवश्यकता है? यदि यह केवल एक बंद गणना है, तो बस एक आभासी स्थान क्यों न बनाएं, जहां पैरामीटर URL में हैं। जब तक आप आंतरिक स्थिति नहीं बदल रहे हैं, तब तक यह ठीक होना चाहिए।
ब्रेटन

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

2
REST "CRUDing Resources" पर आधारित नहीं है। पथ खंडों में अपने सभी क्वेरी मापदंडों को चिपकाकर स्वचालित रूप से एक RESTful इंटरफ़ेस के लिए नहीं बनता है क्योंकि अब आपको लगता है कि आप प्रत्येक क्रमपरिवर्तन को संसाधन कह सकते हैं। दुर्भाग्य से कोई जादू की प्रक्रिया नहीं है जो आप यह पहचानने के लिए आवेदन कर सकते हैं कि आपके सिस्टम में क्या संसाधन होने चाहिए। इसके लिए सावधानीपूर्वक डिजाइन की आवश्यकता होती है, न कि किसी यांत्रिक सूत्र की।
डारेल मिलर

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