REST API क्लाइंट के रूप में एक वेब एप्लिकेशन: संसाधन पहचानकर्ताओं को कैसे संभालना है


21

जब मैं इसे लागू करने की कोशिश करता हूं तो मेरे दिमाग में REST संघर्ष से संबंधित कई अवधारणाएं हैं।

मेरे पास REST-ful बैक-एंड API सिस्टम है जो व्यावसायिक तर्क रखता है, और एक वेब अनुप्रयोग जो UI प्रदान करता है। REST के बारे में विभिन्न संसाधनों से (विशेष रूप से, REST in Practice: Hypermedia and Systems Architecture ) मुझे पता है कि मुझे अपनी संस्थाओं के कच्चे पहचानकर्ताओं को उजागर नहीं करना चाहिए, बल्कि इसके साथ हाइपरलिंक वापस करना चाहिए rel="self"

उदाहरण पर विचार करें। REST एपि में एक संसाधन है जो एक व्यक्ति को लौटाता है:

<Person>
  <Links>
    <Link rel="self" href="http://my.rest.api/api/person/1234"/>
  </Links>
  <Pets>
    <Link rel="pet" href="http://my.rest.api/api/pet/678"/>
  </Pets>
</Person>

समस्या वेब अनुप्रयोग के साथ उत्पन्न होती है। मान लेते हैं कि यह एक पृष्ठ लौटाता है जिसमें ब्राउज़रों के लिए हाइपरलिंक है:

<body class="person">
  <p>
    <a href="http://my.web.app/pet/???????" />
  </p>
</body>

मुझे hrefविशेषता में क्या डालना चाहिए ? उपयोगकर्ता द्वारा लक्ष्य पृष्ठ खोलने पर इकाई पाने में सक्षम होने के लिए मैं वेब एप्लिकेशन में एपीआई इकाई URL कैसे रख सकता हूं?

आवश्यकताएं परस्पर विरोधी लगती हैं:

  1. हाइपरलिंक hrefको वेब एप्लिकेशन पर ले जाना चाहिए क्योंकि यह UI होस्ट करने वाला सिस्टम है
  2. hrefइकाई के कुछ आईडी होना चाहिए क्योंकि वेब अनुप्रयोग इकाई को संबोधित करने के लिए जब लक्ष्य पृष्ठ खुल जाता है में सक्षम होना चाहिए
  3. उल्लेखित पुस्तक कहती है कि वेब ऐप को REST URL को पेरेस / कंस्ट्रक्शन नहीं करना चाहिए क्योंकि यह REST-ful नहीं है

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

इसलिए, मैं सिर्फ 1234एपीआई प्रतिक्रिया URL से नहीं ले सकता क्योंकि एक RESTful ग्राहक के रूप में मुझे इसका इलाज करना चाहिए जैसे कि यह कुछ ऐसा था http://my.rest.api/api/AGRIDd~ryPQZ^$RjEL0j। दूसरी ओर, मुझे कुछ URL देना होगा जो मेरे वेब ऐप की ओर जाता है और यह ऐप के लिए किसी भी तरह से एपीआई के मूल URL को पुनर्स्थापित करने और एपीआई संसाधनों तक पहुंचने के लिए उस URL का उपयोग करने के लिए पर्याप्त है।

सबसे सरल तरीका शायद संसाधनों के एपीआई यूआरएल को उनके स्ट्रिंग पहचानकर्ता के रूप में उपयोग करना है। लेकिन वेब पेज यूआरएल की तरह http://my.web.app/person/http%3A%2F%2Fmy.rest.api%2Fapi%2Fperson%2F1234बदसूरत हैं।

यह सब एक डेस्कटॉप ऐप या सिंगल-पेज जावास्क्रिप्ट ऐप के लिए काफी आसान लगता है। चूँकि वे निरंतर रहते हैं, वे केवल जीवन भर के लिए सेवा की वस्तुओं के साथ यूआरएल को स्मृति में रख सकते हैं और आवश्यकता पड़ने पर उनका उपयोग कर सकते हैं।

एक वेब ऐप के साथ मैं कई तरीकों की कल्पना कर सकता हूं, लेकिन सभी अजीब लगते हैं:

  1. API URL में होस्ट को बदलें और केवल परिणाम रखें। भारी नकारात्मक पक्ष यह है कि एपीआई जो भी URL उत्पन्न करता है उसे संभालने के लिए वेब एप्लिकेशन की आवश्यकता होती है, जिसका अर्थ है राक्षसी युग्मन। इसके अलावा, यह फिर से Restful नहीं है, क्योंकि मेरा वेब ऐप URL की व्याख्या करना शुरू कर देता है।
  2. लिंक के साथ REST API में कच्ची आईडी को उजागर करें, उन्हें वेब ऐप के URL बनाने के लिए उपयोग करें, और फिर API में आवश्यक संसाधनों को खोजने के लिए वेब ऐप सर्वर पर आईडी का उपयोग करें। यह बेहतर है, लेकिन वेब ऐप सर्वर के प्रदर्शन को प्रभावित करेगा क्योंकि वेब ऐप को ब्राउज़र से किसी भी अनुरोध को संभालने के लिए किसी न किसी रूप के गेट-बाय-आईडी अनुरोधों की एक श्रृंखला जारी करने वाले आरईएसटी सेवा नेविगेशन से गुजरना होगा। कुछ नेस्टेड संसाधन के लिए यह महंगा हो सकता है।
  3. सभी स्टोर selfयूआरएल एक लगातार (DB?) वेब अनुप्रयोग सर्वर पर मानचित्रण में API द्वारा दिए। उनके लिए कुछ आईडी बनाएं, वेब एप्लिकेशन पेज URL बनाने के लिए आईडी और REST सेवा संसाधनों के URL प्राप्त करने के लिए उपयोग करें। यानी मैं http://my.rest.api/pet/678URL को एक नई कुंजी के साथ रखता हूं , कहता हूं 3, और वेब पेज URL को जनरेट करता हूं http://my.web.app/pet/3। यह किसी तरह का HTTP कैश कार्यान्वयन जैसा दिखता है। मुझे पता नहीं क्यों, लेकिन यह मुझे अजीब लगता है।

या क्या यह सब मतलब है कि RESTful API वेब एप्लिकेशन के लिए बैकएंड के रूप में सेवा नहीं कर सकता है?


1
यह स्पष्ट नहीं है कि आप क्या हासिल करने की कोशिश कर रहे हैं, शायद इसलिए क्योंकि आपका साधारण इरादा वास्तुकला की परतों के नीचे कवर किया जाता है, इसलिए आप यह कहना मुश्किल है कि क्या "Restful APIs" वास्तव में आपकी मदद करेगा। आपकी समस्या को मैं जो समझता हूं, विकल्प 2 एक सरल और कारगर उपाय है। यहाँ "समस्या" "RESTful APIs" के लिए अंतर्निहित है। RestIsJustSqlReinvented और आप वास्तव में एक ही समस्या में चलेंगे जब आप किसी भी RDBMS से पर्याप्त रूप से जटिल सबग्राफ प्राप्त करने का प्रयास करेंगे। अपने प्रश्नों के लिए अनुकूलित कैश या प्रतिनिधित्व का उपयोग करें।
back2dos

जवाबों:


5

प्रश्न अपडेट को संबोधित करने के लिए संपादित, पिछला उत्तर हटा दिया गया

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

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

<Entity type="Pet">
    <Link rel="self" href="http://example.com/pets/1" />
    <Link rel="owner" href="http://example.com/people/1" />
    <UniqueName>Spot</UniqueName>
</Entity>

अब हम पूरे आवेदन में किसी भी संसाधन आईडी के साथ गड़बड़ किए बिना स्पॉट से फ़िदो तक उस पालतू जानवर का नाम अपडेट कर सकते हैं। इसी तरह हम अपने GUI में उस पालतू जानवर का उल्लेख कुछ इस तरह से कर सकते हैं:

http://example.com/GUI/pets/Spot

यदि पालतू जानवर का मालिक के बिना कोई मतलब नहीं है (या पालतू जानवर को मालिक के बिना सिस्टम में अनुमति नहीं है) तो हम मालिक को सिस्टम में पालतू जानवरों की "पहचान" के हिस्से के रूप में उपयोग कर सकते हैं:

http://example.com/GUI/owners/John/pets/1 (जॉन के लिए सूची में पहला पालतू)

एक छोटा सा नोट, अगर पेट्स और पीपल दोनों एक-दूसरे से अलग हो सकते हैं, तो मैं एपीआई के लिए एंट्री पॉइंट "पीपुल" रिसोर्स नहीं बनाऊंगा। इसके बजाय मैं एक और सामान्य संसाधन बनाऊंगा जिसमें पीपल और पेट्स का लिंक होगा। यह ऐसा संसाधन दे सकता है जो दिखता है:

<Entity type="ResourceList">
    <Link rel="people" href="http://example.com/api/people" />
    <Link rel="pets" href="http://example.com/api/pets" />
</Entity>

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

उपयोगकर्ता अनुप्रयोग में प्रवेश करता है। REST क्लाइंट उन लोगों की संपूर्ण सूची तक पहुँच बनाता है जो उपलब्ध हो सकते हैं:

<Entity type="Person">
    <Link rel="self" href="http://example.com/api/people/1" />
    <Pets>
        <Link rel="pet" href="http://example.com/api/pets/1" />
        <Link rel="pet" href="http://example.com/api/pets/2" />
    </Pets>
    <UniqueName>John</UniqueName>
</Entity>
<Entity type="Person">
    <Link rel="self" href="http://example.com/api/people/2" />
    <Pets>
        <Link rel="pet" href="http://example.com/api/pets/3" />
    </Pets>
    <UniqueName>Jane</UniqueName>
</Entity>

GUI प्रत्येक संसाधन के माध्यम से लूप करेगा और "आईडी" के रूप में UniqueName का उपयोग करके प्रत्येक व्यक्ति के लिए एक सूची आइटम प्रिंट करेगा:

<a href="http://example.com/gui/people/1">John</a>
<a href="http://example.com/gui/people/2">Jane</a>

ऐसा करते समय यह प्रत्येक लिंक को संसाधित कर सकता है जो इसे "पालतू" से संबंधित पाता है और पालतू संसाधन प्राप्त करते हैं जैसे:

<Entity type="Pet">
    <Link rel="self" href="http://example.com/api/pets/1" />
    <Link rel="owner" href="http://example.com/api/people/1" />
    <UniqueName>Spot</UniqueName>
</Entity>

इसके उपयोग से यह लिंक को प्रिंट कर सकता है जैसे:

<!-- Assumes that a pet can exist without an owner -->
<a href="http://example.com/gui/pets/Spot">Spot</a>

या

<!-- Assumes that a pet MUST have an owner -->
<a href="http://example.com/gui/people/John/pets/Spot">Spot</a>

यदि हम पहले लिंक के साथ जाते हैं और यह मानते हैं कि हमारे प्रवेश संसाधन में "पालतू जानवर" के संबंध के साथ एक लिंक है, तो नियंत्रण प्रवाह GUI में कुछ इस तरह होगा:

  1. पृष्ठ खोला गया है और पालतू स्पॉट का अनुरोध किया गया है।
  2. एपीआई प्रविष्टि बिंदु से संसाधनों की सूची लोड करें।
  3. उस संसाधन को लोड करें जो "पालतू जानवर" शब्द से संबंधित है।
  4. "पालतू जानवर" प्रतिक्रिया से प्रत्येक संसाधन के माध्यम से देखें और स्पॉट से मेल खाने वाले एक को ढूंढें।
  5. मौके के लिए जानकारी प्रदर्शित करें।

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


धन्यवाद, माइक। मैंने इसे थोड़ा और स्पष्ट करने के लिए अपना प्रश्न अपडेट किया है। आपके उत्तर के साथ समस्या यह है कि मैं सहमत नहीं हो सकता है कि एक ग्राहक URL को पार्स कर सकता है। यदि ऐसा होता है, तो यह URL के लिए युग्मित हो जाता है। और यह REST के मुख्य विचारों में से एक का उल्लंघन करता है: क्लाइंट को relलिंक चुनने के लिए s का उपयोग करना चाहिए , लेकिन URL की संरचना के किसी भी ज्ञान को नहीं मानना ​​चाहिए। REST एक एपीआई को बदलने के लिए स्वतंत्र है जो यूआरएल को बदलने के लिए स्वतंत्र है बशर्ते कि relवह समान रहे। Parsing URL हमें REST की तुलना में SOAP के करीब ले जाते हैं।
पावेल गातिलोव

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

6

क्या इसका मतलब यह है कि RESTful API वेब एप्लिकेशन के लिए बैकएंड के रूप में काम नहीं कर सकता है?

मैं चुनौती देता हूं कि क्या REST API और वेब एप्लिकेशन के बीच अंतर करना उचित है या नहीं। आपका "वेब अनुप्रयोग" सिर्फ एक ही संसाधनों का वैकल्पिक (एचटीएमएल) अभ्यावेदन होना चाहिए - जो कहने के लिए, मैं कैसे या क्यों आप का उपयोग करने की उम्मीद है समझ में नहीं आता है http://my.rest.api/...और http://my.web.app/...और वे एक साथ एक ही है और अलग-अलग हो सकते हैं।

आपका "क्लाइंट" इस मामले में ब्राउज़र है और यह HTML और जावास्क्रिप्ट को समझता है। यही कारण है कि है मेरी राय में वेब अनुप्रयोग। अब आप असहमत हो सकते हैं और सोच सकते हैं कि आपने foo.com का उपयोग करके वेब एप्लिकेशन का उपयोग किया है और api.foo.com के माध्यम से अन्य सभी चीजों को उजागर किया है - लेकिन आपको फिर पूछना होगा, foo.com ने मुझे संसाधन का प्रतिनिधित्व कैसे प्रदान किया? Foo.com का "बैक-एंड" यह समझने में पूरी तरह सक्षम है कि api.foo.com से संसाधनों की खोज कैसे की जाए। आपका वेब एप्लिकेशन केवल एक प्रॉक्सी बन गया है - यदि आप किसी अन्य एपीआई (किसी और से) से एक साथ बात कर रहे हैं तो इससे अलग नहीं।

तो आपके प्रश्न को सामान्यीकृत किया जा सकता है, "मैं अपने स्वयं के यूआरआई का उपयोग करके संसाधनों का वर्णन कैसे कर सकता हूं जो अन्य प्रणालियों में मौजूद हैं?" जो तुच्छ है जब आप समझते हैं कि यह क्लाइंट (HTML / जावास्क्रिप्ट) नहीं है जो यह समझना चाहिए कि यह कैसे करना है, लेकिन सर्वर। यदि आप मेरी पहली चुनौती से सहमत हैं, तो आप बस अपने वेब एप्लिकेशन को एक अलग REST API के रूप में सोच सकते हैं जो किसी अन्य REST API को प्रॉक्सी या डेलिगेट करता है।

इसलिए जब आपका क्लाइंट पहुँचता my.web.app/pets/1है तो वह पालतू इंटरफ़ेस प्रस्तुत करना जानता है क्योंकि या तो वह जो सर्वर-साइड टेम्पलेट द्वारा लौटाया गया है, या यदि यह कुछ अन्य प्रतिनिधित्व (जैसे JSON या XML) के लिए एक अतुल्यकालिक अनुरोध है, तो सामग्री-प्रकार हेडर इसे बताता है। ।

यह प्रदान करने वाला सर्वर यह समझने के लिए जिम्मेदार है कि एक पालतू जानवर क्या है और रिमोट सिस्टम पर एक पालतू जानवर की खोज कैसे करें। आप यह कैसे करते हैं यह आप पर निर्भर है - आप बस आईडी ले सकते हैं और एक और यूआरआई उत्पन्न कर सकते हैं, जो कि आपको लगता है कि अनुचित है, या आपके पास अपना खुद का डेटाबेस हो सकता है जो दूरस्थ यूआरआई को संग्रहीत करता है और अनुरोध को प्रॉक्सी करता है। इस URI को संग्रहीत करना ठीक है - यह बुकमार्क करने के बराबर है। आप एक अलग डोमेन नाम रखने के लिए यह सब कर रहे होंगे। मैं ईमानदारी से नहीं जानता कि आप ऐसा क्यों चाहते हैं - आपके REST API URI को बुकमार्क-सक्षम भी होना चाहिए।

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


मुझे उम्मीद नहीं है कि वेब ऐप केवल एपी के लिए एक प्रतिनिधित्व होगा। इसके बहुत सारे अंतर हो सकते हैं, उदाहरण के लिए एक ही पृष्ठ पर कुछ मूल के साथ कई बाल संसाधन दिखाएं। मैं नहीं चाहता कि एप के डेटा स्टोरेज की आंतरिक आईडी में वेब एप का आग्रह हो, अगर आप यह कहते हैं कि मुझे यह उम्मीद है कि 2 सिस्टम समान होंगे। मैं यहां प्रदर्शन से चिंतित नहीं हूं, यह समस्या नहीं है। सवाल वास्तव में है 'मैं my.web.app/pets/3REST API Urls को पार्स किए बिना 3 कैसे डालूं'?
पावेल गातिलोव

अपने स्वयं के पुन: कार्य को ठीक करना: 'मैं my.web.app/pets/3संबंधित REST API संसाधन के URL को पार्स किए बिना 3 कैसे डालूं my.rest.api/v0/persons/2/pets/3? या मैं वहाँ क्या रखूँ? '
पावेल गातिलोव

मुझे लगता है कि आप ग्राहक की स्थिति को उस स्थिति का निर्धारण करने वाले भ्रम के साथ भ्रमित कर रहे हैं। आप नहीं रख सकता हूं 3में app/pets/3, क्योंकि app/pets/3अपारदर्शी है, यह जो कुछ भी संसाधन अपने वेब एप्लिकेशन चाहता है के लिए अंक। यदि यह कई अन्य संसाधनों (अन्य प्रणालियों में - आपकी API उनमें से एक है) से बना है, तो यह वेब एप्लिकेशन सर्वर के भीतर उन प्रणालियों के लिए हाइपरलिंक को संग्रहीत करने के लिए आपके ऊपर है, और फिर उन्हें पुनर्प्राप्त करें, उन्हें उनके अभ्यावेदन के लिए हल करें ( जैसे JSON या XML) और फिर अपनी प्रतिक्रिया के हिस्से के रूप में उनकी सेवा करें।
डग

इसे इस तरह से सोचें - अपने एपीआई और ऐप को भूल जाएं। मान लें कि आप एक ऐसी साइट बनाना चाहते हैं जो लोगों को उनके पसंदीदा फेसबुक और ट्विटर पोस्ट एकत्र करने में मदद करे। वे रिमोट सिस्टम हैं। आप URI को अपने सिस्टम के माध्यम से उन सिस्टमों को टनल या टेम्प्लेट करने की कोशिश नहीं करने जा रहे हैं। आप एक 'बोर्ड' संसाधन बना सकते हैं और यह आपका सर्वर होगा जो जानता है कि यह board/1पॉइंट्स facebook.com/post/123और twitter.com/status/789- जब आप अपने बोर्ड का प्रतिनिधित्व प्रदान करने के लिए जाते हैं, तो आपको उन यूआरआई का प्रतिनिधित्व करने के लिए हल करना होगा जिनके साथ आप काम कर सकते हैं। जहां जरूरत हो वहां कैश।
डग

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

5

प्रस्तावना

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


खोज करने के लिए एक निश्चित मात्रा में ज्ञान की आवश्यकता होती है, इसलिए यहां मेरा वास्तविक दुनिया में परिदृश्य है:

मान लें कि हम एक खोज पृष्ठ चाहते हैं, http://my.web.app/personजहां परिणामों में प्रत्येक व्यक्ति के विवरण पृष्ठ का लिंक शामिल हो। एक चीज जो हमारे फ्रंट-एंड कोड को पता होनी चाहिए , वह यह है कि इसके REST डेटा स्रोत के लिए आधार URL कुछ भी हो http://my.rest.api/api। इस URL के GET अनुरोध की प्रतिक्रिया हो सकती है:

<Links>
    <Link ref="self" href="http://my.rest.api/api" />
    <Link rel="person" href="http://my.rest.api/api/person" />
    <Link rel="pet" href="http://my.rest.api/api/pet" />
</Links>

चूंकि हमारा इरादा लोगों की एक सूची प्रदर्शित करना है, इसलिए हम अगले लिंक href GETसे href पर एक अनुरोध भेजते हैं person, जो वापस आ सकता है:

<Links>
    <Link ref="self" href="http://my.rest.api/api/person" />
    <Link rel="search" href="http://my.rest.api/api/person/search" />
</Links>

हम खोज परिणाम प्रदर्शित करना चाहते हैं, इसलिए हम लिंक href पर GETअनुरोध भेजकर खोज सेवा का उपयोग करेंगे search, जो वापस आ सकती है:

<Persons>
    <Person>
        <Links>
            <Link rel="self" href="http://my.rest.api/api/person/1"/>
        </Links>
        <Pets>
            <Link rel="pet" href="http://my.rest.api/api/pet/10"/>
        </Pets>
    </Person>
    <Person>
        <Links>
            <Link rel="self" href="http://my.rest.api/api/person/2"/>
        </Links>
        <Pets>
            <Link rel="pet" href="http://my.rest.api/api/pet/20"/>
        </Pets>
    </Person>
</Persons>

हमारे पास आखिरकार हमारे परिणाम हैं, लेकिन हम अपने फ्रंट-एंड URL कैसे बनाते हैं?

चलिए उस हिस्से को अलग करते हैं जिसे हम कुछ के लिए जानते हैं: एपीआई बेस URL, और बाकी को हमारे सामने के अंत पहचानकर्ता के रूप में उपयोग करें:

  • ज्ञात एपीआई आधार: http://my.rest.api/api
  • व्यक्तिगत इकाई के लिए दिया गया URL: http://my.rest.api/api/person/1
  • एक अलग पहचान: /person/1
  • हमारा आधार URL: http://my.web.app
  • हमारा उत्पन्न फ्रंट-एंड URL: http://my.web.app/person/1

हमारे परिणाम इस तरह दिख सकते हैं:

<ul>
    <li><a href="http://my.web.app/person/1">A person</a></li>
    <li><a href="http://my.web.app/person/2">A person</a></li>
</ul>

एक बार जब कोई उपयोगकर्ता विवरण पृष्ठ पर उस फ्रंट-एंड लिंक का अनुसरण करता है, तो हम GETउस विशिष्ट के विवरण के लिए किस URL को भेजते हैं person? हम बैक-एंड URL को फ्रंट-एंड URL में मैप करने के लिए हमारी विधि जानते हैं, इसलिए हम इसे उल्टा करते हैं:

  • फ्रंट-एंड URL: http://my.web.app/person/1
  • हमारा आधार URL: http://my.web.app
  • एक अलग पहचान: /person/1
  • ज्ञात एपीआई आधार: http://my.rest.api/api
  • जनरेट किया गया URL URL: http://my.rest.api/api/person/1

यदि REST API बदल जाता है जैसे कि एक personURL अब है http://my.rest.api/api/different-person-base/person/1और किसी ने पहले बुकमार्क किया था http://my.web.app/person/1, तो REST API को पुराने URL को नए पर पुनर्निर्देशित करके प्रतिक्रिया देकर कम से कम (एक समय के लिए) उपलब्ध कराना चाहिए। सभी उत्पन्न फ्रंट-एंड लिंक में नई संरचना स्वचालित रूप से शामिल होगी।

जैसा कि आपने शायद देखा है, एपीआई को नेविगेट करने के लिए हमें कई बातें पता होनी चाहिए:

  • एपीआई आधार URL
  • personसंबंध
  • searchसंबंध

मुझे नहीं लगता कि इसमें कुछ भी गलत है; हम किसी भी बिंदु पर एक विशिष्ट URL संरचना नहीं मान रहे हैं, इसलिए निकाय URL की संरचना http://my.rest.api/api/person/1बदल सकती है, और जब तक API बैकवर्ड-संगतता प्रदान करता है, तब भी हमारा कोड काम करेगा।


आपने पूछा कि हमारे रूटिंग लॉजिक दो फ्रंट-एंड URL के बीच अंतर कैसे बता सकते हैं:

  • http://my.rest.api/api/person/1
  • http://my.rest.api/api/pet/3

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

एक विशिष्ट विवरण पृष्ठ पर जाने के लिए, हम उन दो URL को अलग नहीं कर सकते हैं यदि हम selfAPI द्वारा प्रदान किए गए URL की संरचना (यानी अपारदर्शी स्ट्रिंग आईडी) के बारे में किसी भी ज्ञान से बचने के बारे में सख्त हैं । इस काम को करने के लिए, हमारे ज्ञात जानकारी के एक और टुकड़े को शामिल करें - वह इकाई प्रकार, जिसके साथ हम काम कर रहे हैं - हमारे सामने वाले URL में।

पहले हमारे फ्रंट-एंड URL प्रारूप में थे: ${UI base}/${opaque string id}

नया प्रारूप हो सकता है: ${UI base}/${entity type}/${opaque string id}

इसलिए /person/1उदाहरण का उपयोग करते हुए , हम समाप्त करेंगे http://my.web.app/person/person/1

इस प्रारूप के साथ, हमारे यूआई रूटिंग लॉजिक के साथ काम करना होगा /person/person/1, और यह जानते हुए कि स्ट्रिंग में पहला टोकन खुद द्वारा डाला गया था, हम इसे बाहर खींच सकते हैं और उपयुक्त (व्यक्ति, इस उदाहरण में) विस्तार पृष्ठ पर आधारित कर सकते हैं। यदि आप उस URL के बारे में अस्पष्ट महसूस करते हैं, तो हम वहां कुछ और डाल सकते हैं; शायद: http://my.web.app/person/detail/person/1

जिस स्थिति में हम /person/detailरूटिंग के लिए पार्स करेंगे और बाकी का उपयोग अपारदर्शी स्ट्रिंग आईडी के रूप में करेंगे।


मुझे लगता है कि यह एप के लिए वेब एप के बेहद टाइट कपलिंग को पेश करता है।

मैं आपको अनुमान लगा रहा हूं कि चूंकि हमारे जनरेट किए गए फ्रंट-एंड URL में API URL का हिस्सा है, अगर API URL संरचना पुरानी संरचना का समर्थन किए बिना बदल जाती है, तो हमें बुकमार्क URL का अनुवाद करने के लिए कोड परिवर्तन की आवश्यकता होगी। एपीआई यूआरएल का नया संस्करण। दूसरे शब्दों में, यदि REST API किसी संसाधन की ID (अपारदर्शी स्ट्रिंग) को बदल देता है, तो हम पुराने ID का उपयोग करके उस संसाधन के बारे में सर्वर से बात नहीं कर सकते हैं। मुझे नहीं लगता कि हम उस स्थिति में कोड परिवर्तन से बच सकते हैं।

क्या होगा यदि मैं वेब ऐप के लिए URL संरचना को एपीआई से अलग करना चाहता हूं?

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

क्या होगा यदि मेरे वेब ऐप की इकाइयां 1-1 संस्थाओं को मैप नहीं करती हैं?

जवाब रिश्ते पर निर्भर करता है। किसी भी तरह से, आपको एपीआई URL के सामने के छोर को मैप करने के लिए एक रास्ता चाहिए होगा।


मुझे इस दृष्टिकोण के साथ एक समस्या है। यह वास्तव में समाधानों की मेरी सूची में नंबर 1 है। क्या मैं नहीं मिलता है यह है: अगर वेब ऐप्लिकेशन URL और अपारदर्शी तार (बस के रूप में व्यवहार करता है अद्वितीय आईडी व्याख्या नहीं करता है person/1, pet/3), तो यह कैसे पता है कि अगर एक ब्राउज़र को खोलता हैं http://my.rest.api/api/person/1, यह व्यक्ति यूआई दिखाना चाहिए और अगर यह खोलता है http://my.rest.api/api/pet/3, तो पालतू यूआई?
पावेल गातिलोव

अच्छा प्रश्न! मैंने अपनी प्रतिक्रिया के साथ उत्तर को अपडेट कर दिया है।
माइक पार्टरिज

धन्यवाद, माइक। मुझे लगता है कि यह एप के लिए वेब एप के बेहद टाइट कपलिंग को पेश करता है। क्या होगा यदि मैं वेब ऐप के लिए URL संरचना को एपीआई से अलग करना चाहता हूं? क्या होगा यदि मेरे वेब ऐप की इकाइयां 1-1 संस्थाओं को मैप नहीं करती हैं? मुझे अभी भी लगता है कि मैं कुछ पहचानकर्ताओं को उजागर करने के लिए बेहतर तरीका अपनाऊंगा, लेकिन क्लाइंट्स से नेविगेशन के लिए लिंक का उपयोग करने का आग्रह करता हूं।
पावेल गैटिलोव

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

यहां मेरी प्राथमिक चिंता थोड़ी अधिक व्यावहारिक है। मैं वेब ऐप को लागू करने के लिए ASP.NET MVC का उपयोग करता हूं, और कुछ आंतरिक नियमों के कारण मुझे ऐप के समर्थन वाले url पैटर्न को परिभाषित करना पड़ता है। यानी अगर / a / {id} को परिभाषित किया गया है, तो ऐप संभाल लेगा / a / 1, लेकिन नहीं / a / 1 / b / 2। इससे वेब ऐप को फिर से स्थापित करने की आवश्यकता होती है यदि REST API यूआरएल न केवल बुकमार्क किए गए URL को संरक्षित करने के लिए बदलता है, बल्कि रूट से नेविगेट किए जाने पर वेब ऐप को बस काम करने के लिए भी बनाता है। केवल इसलिए कि html पृष्ठों में एम्बेड किए गए हाइपरलिंक उसके बिना काम नहीं करेंगे।
पावेल गातिलोव

2

चलो इसका सामना करते हैं, कोई जादू समाधान नहीं है। क्या आपने रिचर्डसन परिपक्वता मॉडल पढ़ा है ? यह REST आर्किटेक्चर की परिपक्वता को 3 स्तरों में विभाजित करता है: संसाधन, HTTP क्रिया और हाइपरमीडिया नियंत्रण।

मुझे अपनी संस्थाओं के कच्चे पहचानकर्ताओं को उजागर नहीं करना चाहिए, बल्कि rel = "स्व" के साथ हाइपरलिंक वापस करना चाहिए

यह हाइपरमीडिया नियंत्रण है। क्या आपको सचमुच इसकी जरूरत है? इस दृष्टिकोण के कुछ बहुत अच्छे लाभ हैं (आप उनके बारे में यहां पढ़ सकते हैं )। लेकिन मुफ्त भोजन जैसी कोई चीज नहीं है और यदि आप उन्हें प्राप्त करना चाहते हैं तो आपको कड़ी मेहनत करनी होगी (जैसे कि आपका दूसरा उपाय)।

यह संतुलन का सवाल है - क्या आप प्रदर्शन को बलिदान करना चाहते हैं (और अपने कोड को और अधिक जटिल बना सकते हैं) लेकिन एक ऐसी प्रणाली प्राप्त करें जो अधिक लचीली हो? या क्या आप चीजों को तेज और सरल रखना पसंद करते हैं लेकिन बाद में भुगतान करते हैं जब आप अपने एपीआई / मॉडल में बदलाव करते हैं?

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

यदि वेब एप्लिकेशन को तृतीय पक्ष द्वारा विकसित किया गया था या यदि बैकवर्ड संगतता एक समस्या थी, तो हमने अलग तरीके से चुना हो सकता है क्योंकि तब वेब एप्लिकेशन को बदलने के बिना url संरचना को बदलने में सक्षम होने में बहुत महत्व था। कोड को जटिल बनाने के लिए पर्याप्त है।

क्या इसका मतलब यह है कि RESTful API वेब एप्लिकेशन के लिए बैकएंड के रूप में काम नहीं कर सकता है?

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


0

मैं बात करता हूं अगर आप कुछ इसी तरह से चिपके रहते हैं तो आप Atom Syndication Formatअच्छे हैं।

यहां एंट्री का प्रतिनिधित्व करने वाले मेटाडेटा को अतिरिक्त तत्वों / विशेषताओं का उपयोग करके निर्दिष्ट किया जा सकता है:

  • [RFC4287] के अनुसार , इसमें एक URI होता है जो एंट्री को विशिष्ट रूप से पहचानता है

  • [RFC4287] के अनुसार , यह तत्व वैकल्पिक है। यदि इसमें शामिल है तो URI एक ग्राहक को प्रविष्टि को पुनः प्राप्त करने के लिए उपयोग करना चाहिए।

यह सिर्फ मेरे दो सेंट है।


हो सकता है कि मुझे कुछ न मिले, लेकिन मुझे लगता है कि आपका उत्तर यह नहीं समझाता है कि एक वेब ऐप के URL कैसे जनरेट करें जो एक REST API का क्लाइंट है, क्या यह करता है?
पावेल गैटिलोव

0

URLs के बारे में चिंता न करें, मीडिया प्रकारों के बारे में चिंता करें।

यहां देखें (विशेष रूप से तीसरा बुलेट पॉइंट)।

REST API को संसाधनों और ड्राइविंग एप्लिकेशन स्थिति का प्रतिनिधित्व करने के लिए उपयोग किए गए मीडिया प्रकार () को परिभाषित करने में, या मौजूदा मानक मीडिया प्रकारों के लिए विस्तारित संबंध नामों और / या हाइपरटेक्स्ट-सक्षम मार्क-अप को परिभाषित करने में अपने वर्णनात्मक प्रयास के लगभग सभी खर्च करना चाहिए। ।


एक विशिष्ट वेब ऐप के मामले में, ग्राहक एक मानव है ; ब्राउज़र सिर्फ एक एजेंट है

तो एक एंकर टैग की तरह

          <a href="example.com/foo/123">click here</a>

कुछ इस तरह से मेल खाती है

          <link type="text/html" rel="self" href="example.com/foo/123">

URL अभी भी उपयोगकर्ता के लिए अपारदर्शी है, वह सभी के बारे में परवाह करता है मीडिया प्रकार (जैसे text/html, application/pdf, application/flv, video/x-flv, image/jpeg, image/funny-cat-picture etc) हैं। एंकर (और शीर्षक विशेषता में) में निहित वर्णनात्मक पाठ केवल रिश्ते के प्रकार को विस्तार देने का एक तरीका है जो मनुष्यों के लिए समझदारी है।

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

संक्षेप में

बस सुनिश्चित करें कि क्लाइंट (मानव या मशीन) URL के बजाय मीडिया प्रकारों और संबंधों के बारे में परवाह करता है और आप ठीक हो जाएंगे।


रॉड्रिक, मेरा सवाल एपीआई के निर्माण के बारे में नहीं है, बल्कि एक वेब एप्लिकेशन के निर्माण के बारे में है जो एक RESTful API के ऊपर बैठता है। मैं शायद ही समझ सकता हूं कि मीडिया प्रकार मुझे वेब ऐप के लिए URL बनाने में कैसे मदद कर सकते हैं। हालांकि मीडिया प्रकार सेवा अनुबंध और खोज के लिए महत्वपूर्ण हैं।
पावेल गैटिलोव

@PavelGatilov - क्या आपके वेब ऐप का ग्राहक मानव है?
रोड्रिक चैपमैन

हाँ यही है। और एक बहुत ही कम।
पावेल गातिलोव

0

सबसे सरल तरीका शायद संसाधनों के एपीआई यूआरएल को उनके स्ट्रिंग पहचानकर्ता के रूप में उपयोग करना है। लेकिन वेब पेज urls जैसे http://my.web.app/person/http%3A%2F%2Fmy.rest.api%2Fapi%2Fperson%2F1234 बदसूरत हैं।

मुझे लगता है कि आप सही हैं, यह सबसे आसान तरीका है। आप http://my.rest.api/apiउन्हें कम बदसूरत बनाने के लिए URL से रिलेट कर सकते हैं :

http://my.web.app/person/person%2F1234

यदि API द्वारा प्रदान किया गया URL उस आधार के सापेक्ष नहीं होता है, तो यह बदसूरत रूप में बदल जाता है:

http://my.web.app/person/http%3A%2F%2Fother.api.host%2Fapi%2Fperson%2F1234

इसे एक कदम आगे ले जाने के लिए, एपीआई सर्वर से प्रतिक्रिया का निरीक्षण करके यह निर्धारित करें कि आप किस तरह का दृश्य प्रस्तुत करना चाहते हैं और पथ खंड परिसीमन और कॉलन को एन्कोडिंग करना बंद करें:

http://my.web.app/person/1234 (best case)
http://my.web.app/http://other.api.host/api/person/1234 (ugly case)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.