बाकी परिसर / समग्र / नेस्टेड संसाधन [बंद]


177

मैं एक REST आधारित API में अवधारणाओं को संबोधित करने के सर्वोत्तम तरीके से अपना सिर लपेटने की कोशिश कर रहा हूं। अन्य संसाधनों में सम्‍मिलित फ्लैट समस्‍याओं की कोई समस्‍या नहीं है। जहां मैं मुश्किल में चल रहा हूं वे जटिल संसाधन हैं।

उदाहरण के लिए, मेरे पास कॉमिक बुक के लिए एक संसाधन है। ComicBookउस पर गुण के सभी प्रकार की तरह है author, issue number, date, आदि

एक कॉमिक बुक में 1..nकवर की एक सूची भी है । ये कवर जटिल वस्तुएं हैं। वे कवर के बारे में बहुत सारी जानकारी रखते हैं: कलाकार, एक तिथि, और यहां तक ​​कि कवर के आधार 64 एन्कोडेड छवि।

एक के लिए GETपर ComicBookमैं सिर्फ हास्य लौटा सकता है, और उनके base64'ed छवियों सहित कवर के सभी। शायद एक भी कॉमिक पाने के लिए यह कोई बड़ी बात नहीं है। लेकिन मान लीजिए कि मैं एक क्लाइंट ऐप बना रहा हूं जो सिस्टम की सभी कॉमिक्स को एक तालिका में सूचीबद्ध करना चाहता है।
तालिका में ComicBookसंसाधन से कुछ गुण होंगे , लेकिन हम निश्चित रूप से तालिका में सभी कवर प्रदर्शित नहीं करना चाहते हैं। 1000 कॉमिक पुस्तकों को लौटाने, प्रत्येक में कई कवर शामिल होते हैं, जिसके परिणामस्वरूप वायर में बड़ी मात्रा में डेटा आ जाता है, डेटा जो उस मामले में अंतिम उपयोगकर्ता के लिए आवश्यक नहीं है।

मेरी वृत्ति Coverएक संसाधन बनाना है और ComicBookइसमें कवर शामिल हैं। तो अब CoverURI है। GETकॉमिक बुक पर अब काम करता है, विशाल Coverसंसाधन के बजाय हम प्रत्येक कवर के लिए एक यूआरआई भेजते हैं और ग्राहकों को कवर संसाधनों को पुनः प्राप्त कर सकते हैं क्योंकि उन्हें उनकी आवश्यकता होती है।

अब मुझे नई कॉमिक्स बनाने में समस्या है। निश्चित रूप से मैं कम से कम एक कवर बनाना चाहता हूं Comic, जब मैं वास्तव में एक व्यावसायिक नियम बनाऊंगा।
तो अब मैं कर रहा हूँ अटक, मैं या तो ग्राहकों को पहले एक जमा करके व्यापार नियमों को लागू करने के लिए मजबूर Coverहै कि कवर के लिए यूआरआई हो रही है, तो POSTing एक ComicBookसाथ सूची में यूआरआई, या मेरे कि POSTपर ComicBookएक अलग लग रही संसाधन में लेता है यह थूक से बाहर। के लिए आने वाले संसाधन POSTऔर GETगहरी प्रतियां हैं, जहां आउटगोइंग GETएस में निर्भर संसाधनों के संदर्भ हैं।

Coverसंसाधन क्योंकि मैं एक ग्राहक मैं कुछ मामलों में पता कवर दिशा करना चाहते हैं के रूप में यकीन है कि शायद किसी भी मामले में आवश्यक है। तो समस्या निर्भर संसाधन के आकार की परवाह किए बिना सामान्य रूप में मौजूद है। सामान्य तौर पर आप क्लाइंट को मजबूर करने के लिए जटिल संसाधनों को कैसे संभालते हैं बस "पता है" कि उन संसाधनों की रचना कैसे की जाती है?


RESTFUL सेवा का उपयोग करने से क्या समझ में आता है?
treecoder

1
मैं HATEAOS का पालन करने की कोशिश कर रहा हूं, जो मेरे दिमाग में, कुछ इस तरह का उपयोग करने के लिए काउंटर चलाता है, लेकिन मैं एक नज़र डालूंगा।
jgerman

एक ही भावना में अलग सवाल। हालाँकि स्वामित्व आपके प्रस्तावित समाधान (प्रश्न में एक) से भिन्न है। stackoverflow.com/questions/20951419/…
वेस

जवाबों:


64

@ray, उत्कृष्ट चर्चा

@jgerman, यह मत भूलिए कि यह REST है, इसका मतलब यह नहीं है कि संसाधनों को POST से पत्थर में सेट किया जाना है।

किसी संसाधन के किसी दिए गए प्रतिनिधित्व में शामिल करने के लिए आप क्या चुनते हैं, यह आपके ऊपर है।

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

कवर का आपका विशिष्ट मामला थोड़ा अधिक जटिल है कि एक कवर में वास्तव में एक कॉमिक बुक, और वीज़ा वर्सा की आवश्यकता होती है।

हालाँकि, यदि आप एक ईमेल संदेश को संसाधन के रूप में मानते हैं, और पते को बाल संसाधन के रूप में मानते हैं, तो आप स्पष्ट रूप से पते से अलग से संदर्भ ले सकते हैं। उदाहरण के लिए, सभी पते से प्राप्त करें। या, पते से पिछले के साथ एक नया संदेश बनाएं। यदि ईमेल REST था, तो आप आसानी से देख सकते हैं कि कई क्रॉस-संदर्भित संसाधन उपलब्ध हो सकते हैं: / प्राप्त-संदेश, / ड्राफ्ट-संदेश, / पते से, /-पते, / पते, / विषय, / संलग्नक, / फ़ोल्डर , / टैग, / श्रेणियां, / लेबल, एट अल।

यह ट्यूटोरियल क्रॉस-संदर्भित संसाधनों का एक शानदार उदाहरण प्रदान करता है। http://www.peej.co.uk/articles/restfully-delicious.html

यह स्वचालित रूप से जनरेट किए गए डेटा के लिए सबसे सामान्य पैटर्न है। उदाहरण के लिए, आप नए संसाधन के लिए URI, ID, या निर्माण तिथि पोस्ट नहीं करते हैं, क्योंकि ये सर्वर द्वारा उत्पन्न होते हैं। और फिर भी, नए संसाधन वापस मिलने पर आप URI, ID, या निर्माण तिथि पुनः प्राप्त कर सकते हैं।

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

प्रपत्र और पैरामीटर संसाधनों के HTML अभ्यावेदन से पहले से अलग हैं। बाइनरी / फ़ाइल पैरामीटर पोस्ट करना, जिसके परिणामस्वरूप URL में खिंचाव नहीं है।

जब आप किसी नए संसाधन (/ कॉमिक-बुक्स / नए) के लिए फॉर्म प्राप्त करते हैं, या किसी संसाधन (/ कॉमिक-बुक्स / 0 / एडिट) को संपादित करने के लिए फॉर्म प्राप्त करते हैं, तो आप संसाधन के एक फॉर्म-विशिष्ट प्रतिनिधित्व के लिए पूछ रहे हैं। यदि आप इसे सामग्री-प्रकार "एप्लिकेशन / x-www-form-urlencoded" या "मल्टीपार्ट / फॉर्म-डेटा" के साथ संसाधन संग्रह पर पोस्ट करते हैं, तो आप सर्वर से उस प्रकार के प्रतिनिधित्व को बचाने के लिए कह रहे हैं। सर्वर HTML प्रतिनिधित्व के साथ प्रतिक्रिया कर सकता है जो सहेजा गया था, या जो भी हो।

आप किसी HTML, XML या JSON रिप्रजेंटेशन के लिए रिसोर्स कलेक्शन पर पोस्ट करने की भी अनुमति दे सकते हैं, एक एपीआई या इसी तरह के प्रयोजनों के लिए।

आपके संसाधनों और वर्कफ़्लो का प्रतिनिधित्व करना भी संभव है जैसा कि आप वर्णन करते हैं, कॉमिक बुक के बाद पोस्ट कवर में लेते हैं, लेकिन कॉमिक पुस्तकों को कवर करने की आवश्यकता होती है। उदाहरण इस प्रकार है।

  • विलंबित कवर निर्माण की अनुमति देता है
  • आवश्यक कवर के साथ कॉमिक बुक निर्माण की अनुमति देता है
  • कवरों को क्रॉस-रेफ़र किया जा सकता है
  • कई कवर की अनुमति देता है
  • ड्राफ्ट कॉमिक बुक बनाएं
  • ड्राफ्ट कॉमिक बुक कवर बनाएं
  • मसौदा कॉमिक बुक प्रकाशित करें

GET / कॉमिक-पुस्तकें
=> 200 ठीक, सभी कॉमिक पुस्तकें प्राप्त करें।

GET / कॉमिक-बुक्स / 0
=> 200 ओके, कवर (/ कवर / 1, / कवर / 2) के साथ कॉमिक बुक (आईडी: 0) प्राप्त करें।

GET / कॉमिक-बुक्स / 0 / कवर
=> 200 ओके, कॉमिक बुक के लिए कवर प्राप्त करें (आईडी: 0)।

प्राप्त / कवर
=> 200 ठीक है, सभी कवर प्राप्त करें।

जीईटी / कवर / 1
=> 200 ओके, कॉमिक बुक (/ कॉमिक-बुक्स / 0) के साथ कवर (आईडी: 1) प्राप्त करें।

GET / कॉमिक-बुक्स / नई
=> 200 ओके, कॉमिक बुक बनाने के लिए फॉर्म प्राप्त करें (फॉर्म: POST / ड्राफ्ट-कॉमिक-बुक्स)।

POST / ड्राफ्ट-कॉमिक-बुक्स
शीर्षक = foo
लेखक = बू
प्रकाशक = goo
प्रकाशित = २०११-०१-०१
= = ३०२ मिला, स्थान: / ड्राफ्ट-कॉमिक-बुक्स / ३, रीडायरेक्ट टू कॉमिक बुक (आईडी: ३) कवर (बाइनरी)।

GET / ड्राफ्ट-कॉमिक-बुक्स / 3
=> 200 ओके, कवर के साथ ड्राफ्ट कॉमिक बुक (id: 3) प्राप्त करें।

GET / ड्राफ्ट-कॉमिक-बुक्स / 3 / कवर
=> 200 ओके, ड्राफ्ट कॉमिक बुक (/ ड्राफ्ट-कॉमिक-बुक / 3) के लिए कवर प्राप्त करें।

GET / ड्राफ्ट-कॉमिक-बुक्स / 3 / कवर / न्यू
=> 200 ओके, ड्राफ्ट कॉमिक बुक (/ ड्राफ्ट-कॉमिक-बुक / 3) के लिए कवर बनाने के लिए फॉर्म प्राप्त करें (फॉर्म: POST / ड्राफ्ट-कॉमिक-बुक्स / 3 / कवर)।

POST / ड्राफ्ट-कॉमिक-बुक्स / 3 / कवर
cover_type = फ्रंट
कवर_data = (बाइनरी)
=> 302 मिला, स्थान: / ड्राफ्ट-कॉमिक-बुक्स / 3 / कवर, ड्राफ्ट कॉमिक बुक (ड्राफ्ट-कॉमिक) के लिए नए कवर पर रीडायरेक्ट -book / 3 / कवर / 1)।

GET / ड्राफ्ट-कॉमिक-बुक्स / 3 / पब्लिश
=> 200 ओके, ड्राफ्ट कॉमिक बुक (id: 3) (फॉर्म: POST / प्रकाशित-कॉमिक-बुक्स) प्रकाशित करने के लिए फॉर्म प्राप्त करें।

POST / प्रकाशित-कॉमिक-पुस्तकों का
शीर्षक = foo
लेखक = बू
प्रकाशक = goo
प्रकाशित = 2011-01-01
cover_type = front
cover_data = (बाइनरी)
=> 302 मिला, स्थान: / कॉमिक-पुस्तकें / 3, प्रकाशित कॉमिक बुक के लिए पुनर्निर्देशित (आईडी: 3) कवर के साथ।


मैं इसके लिए कुल नौसिखिया हूं, और इसे जल्दी में सीखने की कोशिश कर रहा हूं। मुझे यह बेहद मददगार लगा। हालाँकि, अन्य ब्लॉगों में आज मैं पढ़ रहा हूँ, एक ऑपरेशन करने के लिए जीईटी का उपयोग (विशेषकर एक ऐसा ऑपरेशन जो बेकार नहीं है) पर किया जाएगा। तो क्या यह पोस्ट / ड्राफ्ट-कॉमिक-बुक्स / 3 / पब्लिश नहीं होना चाहिए?
गैरी मैकगिल

3
@GaryMcGill उनके उदाहरण में, ड्राफ्ट-कॉमिक-बुक्स / 3 / प्रकाशित केवल एक HTML फॉर्म लौटाता है (कोई डेटा संशोधित नहीं करता है)।
ओलिवियर लालोंडे

@ ऑलिवर सही है। शब्द प्रकाशित होता है, यह बताने के लिए कि फॉर्म क्या करता है। हालाँकि, क्योंकि आप क्रियाओं को HTTP विधियों तक सीमित रखना चाहते हैं, इसलिए आपको प्रकाशित कॉमिक पुस्तकों के लिए एक संसाधन पर पोस्ट करना चाहिए। ... यदि यह एक वेबसाइट होती, तो आपको कुछ प्रकाशित करने के लिए फॉर्म के लिए URI की आवश्यकता होती। ... हालाँकि, यदि प्रकाशित कार्रवाई कॉमिक बुक पेज पर केवल एक बटन थी, तो वह सिंगल-बटन फॉर्म सीधे / प्रकाशित-कॉमिक-पुस्तकों के यूआरआई पर पोस्ट कर सकता है।
एलेक्स

@ एलेक्स, POST रिक्वेस्ट में मैं एक 201 क्रिएट किया जाएगा, जिसके जवाब में हेडर के रूप में नए संसाधन का URL होगा।
ismriv

2
@ स्टेफ़ेन, रीडायरेक्ट सिर्फ नियंत्रकों के लिए सब कुछ सरल बनाता है। यहां तक ​​कि एक एपीआई के लिए, नई सामग्री के लिए स्थान बनाने वाले नियंत्रक को वापस करना सरल होता है, और फिर शो नियंत्रक को नई सामग्री के प्रदर्शन को संभालने देता है। हालाँकि, यह केवल सामग्री प्राप्त करने और रीडायरेक्ट से परेशान न होने के लिए एपीआई के क्लाइंट के लिए अच्छा / सरल है।
एलेक्स

45

संसाधनों के रूप में कवर करना निश्चित रूप से REST की भावना में है, विशेष रूप से HATEOAS। तो हां, आपको एक पुस्तक का प्रतिनिधित्व GETकरने का अनुरोध किया http://example.com/comic-books/1जाएगा, जिसमें कवर के लिए यूआरआई का एक सेट सहित गुण हैं। अब तक सब ठीक है।

आपका सवाल है कि कॉमिक बुक क्रिएशन से कैसे निपटें। यदि आपका व्यवसाय नियम यह था कि एक पुस्तक में 0 या अधिक कवर होंगे, तो आपको कोई समस्या नहीं है:

POST http://example.com/comic-books

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

POST http://example.com/comic-books/8/covers

निकाय निकाय में कवर के साथ।

अब आपके पास एक अच्छा प्रश्न है कि क्या होता है यदि आपका व्यवसाय नियम कहता है कि हमेशा कम से कम एक कवर होना चाहिए। यहाँ कुछ विकल्प दिए गए हैं, जिनमें से पहला आपने अपने प्रश्न में पहचाना है:

  1. पहले एक कवर के निर्माण को मजबूर करें, अब अनिवार्य रूप से एक गैर-निर्भर संसाधन को कवर कर रहा है, या आप प्रारंभिक कवर को POST की इकाई संस्था में रखते हैं जो कॉमिक बुक बनाता है। जैसा कि आप कहते हैं कि इसका मतलब यह है कि आप जिस POST को बनाने के लिए प्रतिनिधित्व करते हैं, वह आपके GET के प्रतिनिधित्व से अलग होगा।

  2. प्राथमिक या प्रारंभिक, या पसंदीदा, या अन्यथा-निर्दिष्ट कवर की धारणा को परिभाषित करें। यह संभवत: एक मॉडलिंग हैक है, और यदि आपने ऐसा किया है कि यह एक तकनीक को फिट करने के लिए आपके ऑब्जेक्ट मॉडल (आपके वैचारिक या व्यावसायिक मॉडल) को ट्विक करने जैसा होगा। महान विचार नहीं है।

आपको इन दो विकल्पों का वजन कम करना चाहिए, जिसमें केवल कवरलेस कॉमिक्स की अनुमति हो।

आपको कौन से तीन विकल्प लेने चाहिए? अपनी स्थिति के बारे में बहुत अधिक नहीं जानना, लेकिन सामान्य 1. उत्तर पर निर्भर संसाधन प्रश्न, मैं कहूंगा:

  • यदि आप अपनी रेस्टफुल सर्विस लेयर के लिए 0..N के साथ जा सकते हैं, तो बढ़िया। शायद कम से कम एक की आवश्यकता होने पर आपके RESTful SOA के बीच एक परत आगे के व्यावसायिक अवरोध को संभाल सकती है। (यह निश्चित नहीं है कि यह कैसा दिखेगा लेकिन यह देखने लायक हो सकता है .... अंतिम उपयोगकर्ता आमतौर पर SOA को वैसे भी नहीं देखते हैं।)

  • यदि आपको बस 1..N बाधा का मॉडल बनाना चाहिए, तो अपने आप से पूछें कि क्या कवर सिर्फ श्रावक संसाधन हो सकते हैं, दूसरे शब्दों में, वे कॉमिक पुस्तकों के अलावा अन्य चीजों पर मौजूद हो सकते हैं। अब वे निर्भर संसाधन नहीं हैं और आप उन्हें पहले बना सकते हैं और कॉमिक बुक बनाने वाले अपने POST में URI की आपूर्ति कर सकते हैं।

  • यदि आपको 1..N की आवश्यकता है और कवर निर्भर रहते हैं, तो बस अपनी वृत्ति को POST में प्रतिनिधित्व बनाए रखने के लिए आराम करें और समान प्राप्त करें, या उन्हें समान बनाएं।

अंतिम आइटम को इस तरह समझाया गया है:

<comic-book>
  <name>...</name>
  <edition>...</edition>
  <cover-image>...BASE64...</cover-image>
  <cover-image>...BASE64...</cover-image>
  <cover>...URI...</cover>
  <cover>...URI...</cover>
</comic-book>

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

इसलिए मूल रूप से आप POST और GET अभ्यावेदन को "समान होने" की अनुमति दे रहे हैं, लेकिन आप केवल GET पर "कवर" छवि का उपयोग न करें और न ही POST पर कवर करें। आशा है कि समझ में आता है।

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