रेस्टफुल एपीआई। क्या मुझे उस वस्तु को वापस करना चाहिए जो बनाई गई / अद्यतन की गई?


36

मैं WebApi का उपयोग करके एक RESTful वेब सेवा को डिज़ाइन कर रहा हूं और सोच रहा था कि वस्तुओं को अपडेट / निर्माण करते समय वापस आने के लिए HTTP प्रतिक्रियाओं और प्रतिक्रिया निकायों का क्या मतलब है।

उदाहरण के लिए, मैं कुछ JSON को वेब सेवा में भेजने के लिए POST विधि का उपयोग कर सकता हूं और फिर एक ऑब्जेक्ट बना सकता हूं। क्या तब (201) या ठीक (200) HTTP स्थिति को सेट करने के लिए सबसे अच्छा अभ्यास है और बस "नया कर्मचारी जोड़ा" जैसे संदेश लौटाएं, या मूल रूप से भेजे गए ऑब्जेक्ट को वापस करें?

वही PUT विधि के लिए जाता है। किस HTTP स्थिति का उपयोग करना सबसे अच्छा है और क्या मुझे उस वस्तु को वापस करने की आवश्यकता है जो बनाई गई थी या सिर्फ एक संदेश? इस तथ्य को ध्यान में रखते हुए कि उपयोगकर्ता जानता है कि वे किस वस्तु को बनाने / अपडेट करने का प्रयास कर रहे हैं।

कोई विचार?

उदाहरण:

नया कर्मचारी जोड़ें:

POST /api/employee HTTP/1.1
Host: localhost:8000
Content-Type: application/json

{
    "Employee": {
        "Name" : "Joe Bloggs",
        "Department" : "Finance"
    }
}

मौजूदा कर्मचारी को अपडेट करें:

PUT /api/employee HTTP/1.1
Host: localhost:8000
Content-Type: application/json

{
    "Employee": {
        "Id" : 1
        "Name" : "Joe Bloggs",
        "Department" : "IT"
    }
}

जवाब:

निर्मित / अद्यतन वस्तु के साथ प्रतिक्रिया

HTTP/1.1 201 Created
Content-Length: 39
Content-Type: application/json; charset=utf-8
Date: Mon, 28 Mar 2016 14:32:39 GMT

{
    "Employee": {
        "Id" : 1
        "Name" : "Joe Bloggs",
        "Department" : "IT"
    }
}

केवल संदेश के साथ प्रतिक्रिया:

HTTP/1.1 200 OK
Content-Length: 39
Content-Type: application/json; charset=utf-8
Date: Mon, 28 Mar 2016 14:32:39 GMT

{
    "Message": "Employee updated"
}

केवल स्थिति कोड के साथ प्रतिक्रिया:

HTTP/1.1 204 No Content
Content-Length: 39
Date: Mon, 28 Mar 2016 14:32:39 GMT

2
अच्छा सवाल है, लेकिन "बेस्ट-प्रैक्टिस" शब्द का उपयोग करना इस साइट meta.programmers.stackexchange.com/questions/2442/ पर टैबू की तरह है। आप शायद इस सवाल का दोबारा इस्तेमाल करना चाहते हैं। meta.programmers.stackexchange.com/questions/6967/…
स्नूप

3
एक अनुवर्ती के रूप में, क्या अनुरोध में एक ध्वज होना अच्छा होगा, ताकि (उदाहरण के लिए) एक मोबाइल एप्लिकेशन को वाईफाई पर होने पर पूरी वस्तु वापस मिल सके, लेकिन सेलुलर डेटा का उपयोग करते समय केवल आईडी? क्या ऐसा हेडर है जो JSON को प्रदूषित करने से बचाने के लिए इस्तेमाल किया जाना चाहिए?
एंड्रयू

@AndrewPiliser दिलचस्प विचार, हालांकि मुझे व्यक्तिगत रूप से लगता है कि यह केवल एक दृष्टिकोण लेने और इसे करने के लिए सबसे अच्छा है। फिर जैसे-जैसे आपका एप्लिकेशन विकसित होता है या अधिक लोकप्रिय होता जाता है, इसे अनुकूलित करें
iswinky

@AndrewPiliser आपका विचार UPDATE/INSERT ... RETURNINGSQL के लिए Postgresql संस्करण के समान है । यह अत्यंत उपयोगी है, विशेष रूप से क्योंकि यह नए डेटा को प्रस्तुत करता है और अद्यतन संस्करण परमाणु के लिए अनुरोध करता है।
बेलाजज

जवाबों:


31

ज्यादातर चीजों के साथ, यह निर्भर करता है। आपका ट्रेडऑफ़ नेटवर्क आकार बनाम उपयोग में आसानी है। यह ग्राहकों के लिए बनाए गए संसाधन को देखने के लिए बहुत मददगार हो सकता है। इसमें सर्वर द्वारा आबादी वाले क्षेत्र शामिल हो सकते हैं, जैसे कि अंतिम निर्माण-समय। चूँकि आप idउपयोग करने के बजाय शामिल होना hateoasचाहते हैं, ग्राहक संभवतः उस संसाधन के लिए आईडी देखना चाहेंगे जिसे वे अभी POSTसंपादित करते हैं।

यदि आपने बनाया संसाधन शामिल नहीं किया है, तो कृपया एक मनमाना संदेश न बनाएँ। 2xx और स्थान फ़ील्ड ग्राहकों के लिए यह सुनिश्चित करने के लिए पर्याप्त जानकारी है कि उनका अनुरोध ठीक से संभाला गया था।


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

3
+1 पर "कृपया एक मनमाना संदेश न बनाएं" सलाह
HairOfTheDog

क्या "कोई मनमाना संदेश" स्ट्रिंग संदेशों या किसी भी वापसी मूल्य पर ध्यान केंद्रित नहीं करता है जो निर्मित संसाधन नहीं है? मैं उन मामलों पर ध्यान केंद्रित कर रहा हूं जहां हम निर्मित संसाधन की आईडी वापस करते हैं (लेकिन स्वयं संसाधन नहीं) और सोच रहा था कि यह कहां फिट बैठता है?
फ्लोटर

12

निजी तौर पर, मैं हमेशा केवल वापसी करता हूं 200 OK

अपने प्रश्न को उद्धृत करने के लिए

इस तथ्य को ध्यान में रखते हुए कि उपयोगकर्ता जानता है कि वे किस वस्तु को बनाने / अपडेट करने का प्रयास कर रहे हैं।

ग्राहक को यह बताने के लिए कि वह अतिरिक्त बैंडविड्थ (जिसके लिए भुगतान करना पड़ सकता है) क्यों जोड़ रहा है?


1
यही मैं सोच रहा था, अगर यह अमान्य है तो आप सत्यापन संदेश वापस कर सकते हैं, लेकिन यदि यह मान्य है और बनाया / अपडेट किया गया है, तो HTTP स्थिति कोड की जांच करें और उपयोगकर्ता को एक संदेश दिखाएं जैसे कि "हुर्रे" उस पर आधारित है
iswinky

3
JQuery और इस तरह के भ्रम से बचने के लिए, stackoverflow.com/a/827045/290182 के बारे में 200/ देखें 204 No Content
बेलादज़

10

@iswinky मैं हमेशा POST और PUT दोनों के मामले में पेलोड को वापस भेजूंगा।

POST के मामले में आप आंतरिक आईडी या UUID के साथ इकाई बना सकते हैं। इसलिए यह पेलोड को वापस भेजने के लिए समझ में आता है।

इसी तरह, PUT के मामले में, आप उपयोगकर्ता के कुछ क्षेत्रों (अपरिवर्तनीय मान, कह सकते हैं) को अनदेखा कर सकते हैं, या PATCH के मामले में, डेटा अन्य उपयोगकर्ताओं द्वारा भी बदला जा सकता है।

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

यह केवल एक DELETE के मामले में है कि मैं पेलोड को वापस नहीं भेजूंगा और एक प्रतिक्रिया सामग्री के साथ 200 या कोई प्रतिक्रिया सामग्री के साथ 204 करेगा।

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

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

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

इस मामले में कि ऑब्जेक्ट बहुत बड़ा है या पैरेंट ऑब्जेक्ट अपडेट किया जा रहा है, तो मैं नेस्टेड संरचनाओं को hrefs के रूप में वापस भेजूंगा।

लब्बोलुआब यह है कि मैं निश्चित रूप से उस डेटा को वापस भेजने की कोशिश करूंगा जो उपभोक्ता / यूआई के लिए तुरंत प्रक्रिया करने के लिए समझ में आता है और परमाणु एपीआई कार्रवाई के साथ किया जाना चाहिए बजाय यूआई पोस्ट अपडेट करने के लिए 2-5 और एपीआई प्राप्त करना होगा। डेटा का निर्माण / अद्यतन।

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


मैं कई स्थितियों को देख सकता हूं जहां पूरे पेलोड को वापस भेजना एक बुरा विचार है, जब पेलोड बड़ा होता है।
बेलाजज

2
@ बिल्लाज पूरी तरह से सहमत हैं। YMMV REST API के डिज़ाइन पर आधारित है। मैं आमतौर पर बहुत बड़ी वस्तुओं से बचता हूं और इसे उप-संसाधनों / PUTs की एक श्रृंखला में तोड़ देता हूं। यदि पेलोड बहुत बड़ा है, तो ऐसा करने के बेहतर तरीके हैं, और उसमें आप HATEOAS करना चाहते हैं (जैसे मार्जन ऊपर कहते हैं) जहां आप ऑब्जेक्ट के बजाय ऑब्जेक्ट का संदर्भ वापस करते हैं।
ksprashu

@ksprashu: "इसलिए यह पेलोड को वापस भेजने के लिए समझ में आता है" - मुझे लगता है कि यह एक बुरा विचार है, क्योंकि इस प्रकार एक संसाधन कई तरीकों से प्राप्त किया जा सकता है: जीईटी के माध्यम से, पीओटी की प्रतिक्रिया के रूप में, पीयूटी की प्रतिक्रिया के रूप में। इसका मतलब है कि ग्राहक संभावित अलग संरचना के साथ 3 संसाधन प्राप्त करता है । जैसे कि यदि आप बिना शरीर के केवल यूआरआई (स्थान) वापस लौटेंगे, तो संसाधन प्राप्त करने का एकमात्र तरीका जीईटी होगा। यह सुनिश्चित करता है कि ग्राहक हमेशा लगातार प्रतिक्रियाएं प्राप्त करता है।
मेंटलबर्ग

@mentallurg मुझे एहसास है कि मैंने यह अधिकार नहीं लिया है। इस पर ध्यान दिलाने के लिए धन्यवाद। मैंने अपना उत्तर संपादित कर दिया है। मुझे पता है अगर यह अधिक समझ में आता है।
ksprashu

जब तक आप अपने घर के काम के लिए एक सेवा को लागू करते हैं, तब तक वास्तव में कोई फर्क नहीं पड़ता। जैसा चाहो वैसा करो। अपना समय बचाओ।
मेंटलबर्ग

9

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

उदाहरण के लिए आप निम्न उदाहरण को संदर्भित कर सकते हैं जो कर्मचारी ऑब्जेक्ट को डेटाबेस में सहेजता है और प्रतिक्रिया के रूप में नए बनाए गए संसाधन ऑब्जेक्ट का URL लौटाता है।

@RequestMapping(path = "/employees", method = RequestMethod.POST)
public ResponseEntity<Object> saveEmployee(@RequestBody Employee employee) {
        int id = employeeService.saveEmployee(employee);
        URI uri = ServletUriComponentsBuilder.fromCurrentRequest().path("/{id}").buildAndExpand(id).toUri();
        return ResponseEntity.created(uri).build();
}

यह बाकी समापन बिंदु इस प्रकार प्रतिक्रिया देगा:

स्थिति 201 - बनाई गई

हेडर स्थान → http: // localhost: 8080 / कर्मचारी / 1


अच्छा और साफ - अब और इसके बाद का पालन करने वाले
हसन तारेक

0

मैं एक HTTP पैरामीटर को रिटर्न बॉडी सशर्त में एक पेलोड बनाऊंगा।

अनावश्यक राउंड ट्रिप से बचने के लिए अक्सर एपीआई उपभोक्ता के पास किसी प्रकार की सामग्री को वापस करने के लिए सबसे अच्छा नहीं है (कारणों में से एक है)।

तथ्य की बात के रूप में, क्योंकि हमारे अनुप्रयोग अधिक डेटा-गहन और वितरित हो जाते हैं, मैं इस दिशानिर्देश का पालन करने की कोशिश करता हूं:

मेरा दिशानिर्देश :

किसी भी समय एक उपयोग का मामला है जो POST या PUT के तुरंत बाद GET की मांग करता है, यह एक ऐसा मामला है जहां केवल POST / PUT प्रतिक्रिया में कुछ वापस करना सबसे अच्छा हो सकता है।

यह कैसे किया जाता है, और PUT या POST से वापस लौटने के लिए किस प्रकार की सामग्री है, यह एप्लिकेशन विशिष्ट है। अब, यह दिलचस्प होगा यदि एप्लिकेशन प्रतिक्रिया निकाय में "सामग्री" के प्रकार को परिचालित कर सकता है (क्या हम नई वस्तु का स्थान चाहते हैं, या कुछ फ़ील्ड, या संपूर्ण ऑब्जेक्ट, आदि)

एक आवेदन पैरामीटर का एक सेट परिभाषित कर सकता है एक POST / PUT प्रतिक्रिया शरीर में वापस जाने के लिए "सामग्री" के प्रकार को नियंत्रित करने के लिए प्राप्त कर सकता है। या यह एक पैरामीटर के रूप में कुछ प्रकार के ग्राफक्यूएल क्वेरी को सांकेतिक शब्दों में बदलना कर सकता है (मैं इसे उपयोगी होने के नाते देख सकता हूं लेकिन रखरखाव दुःस्वप्न भी बन सकता हूं।)

किसी भी तरह से, यह मुझे लगता है कि:

  1. POST / PUT प्रतिक्रिया निकाय में कुछ वापस करना ठीक है (और सबसे अधिक संभावना है)।
  2. यह कैसे किया जाता है आवेदन-विशिष्ट और सामान्यीकरण के लिए लगभग असंभव है।
  3. आप बड़े आकार के "संदर्भ" को डिफ़ॉल्ट रूप से वापस नहीं करना चाहते हैं (ट्रैफ़िक-शोर जो POST के बाद GETs से दूर जाने के पूरे कारण को हरा देता है।)

तो, 1) इसे करें, लेकिन 2) इसे सरल रखें।

एक अन्य विकल्प मैंने देखा है कि लोग POST / PUT के लिए वैकल्पिक अंत बिंदु (कहते हैं, / ग्राहक बनाते हैं कि शरीर में कुछ भी नहीं लौटाते हैं और / ग्राहक_with_details POST / PUT / ग्राहकों के लिए, लेकिन प्रतिक्रिया शरीर में कुछ वापस करते हैं।

मैं इस दृष्टिकोण से बचूंगा, हालाँकि। क्या होता है जब आपको वैध रूप से विभिन्न प्रकार की सामग्री को वापस करने की आवश्यकता होती है? सामग्री प्रकार प्रति एक समापन बिंदु? स्केलेबल या रखरखाव योग्य नहीं है।

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