https.onCall के लिए प्रोटोकॉल से जुड़ी ज़रूरी शर्तें

Cloud Functions के लिए https.onCall ट्रिगर, एचटीटीपीएस ट्रिगर होता है. इसमें अनुरोध और रिस्पॉन्स के लिए एक खास फ़ॉर्मैट होता है. इस सेक्शन में, एचटीटीपीएस रिक्वेस्ट और रिस्पॉन्स फ़ॉर्मैट के बारे में जानकारी दी गई है. इनका इस्तेमाल, एपीआई को लागू करने के लिए क्लाइंट SDKs करते हैं. अगर Android, Apple प्लैटफ़ॉर्म या वेब SDK टूल का इस्तेमाल करके आपकी ज़रूरतें पूरी नहीं की जा सकतीं, तो यह जानकारी आपके लिए मददगार हो सकती है.

अनुरोध का फ़ॉर्मैट: हेडर

कॉल किए जा सकने वाले ट्रिगर एंडपॉइंट पर भेजा जाने वाला एचटीटीपी अनुरोध, POST होना चाहिए. साथ ही, उसमें ये हेडर होने चाहिए:

  • ज़रूरी है: Content-Type: application/json
    • ; charset=utf-8 को इस्तेमाल करने की अनुमति है. हालांकि, ऐसा करना ज़रूरी नहीं है.
  • ज़रूरी नहीं: Authorization: Bearer <token>
    • अनुरोध करने वाले लॉग इन किए हुए उपयोगकर्ता के लिए Firebase Authentication यूज़र आईडी टोकन. बैकएंड इस टोकन की पुष्टि अपने-आप करता है और इसे हैंडलर के context में उपलब्ध कराता है. अगर टोकन मान्य नहीं है, तो अनुरोध अस्वीकार कर दिया जाता है.
  • ज़रूरी नहीं: Firebase-Instance-ID-Token: <iid>
    • Firebase क्लाइंट SDK टूल से मिला FCM रजिस्ट्रेशन टोकन. यह स्ट्रिंग होनी चाहिए. यह हैंडलर के context में उपलब्ध है. इसका इस्तेमाल, पुश नोटिफ़िकेशन को टारगेट करने के लिए किया जाता है.
  • ज़रूरी नहीं: X-Firebase-AppCheck: <token>
    • अनुरोध करने वाले क्लाइंट ऐप्लिकेशन से मिला Firebase App Check टोकन. बैकएंड इस टोकन की पुष्टि अपने-आप करता है और उसे डिकोड करता है. साथ ही, हैंडलर के context में appId को इंजेक्ट करता है. अगर टोकन की पुष्टि नहीं की जा सकती है, तो अनुरोध अस्वीकार कर दिया जाता है. (SDK टूल के 3.14.0 और उसके बाद के वर्शन के लिए उपलब्ध है)

अगर कोई अन्य हेडर शामिल किया जाता है, तो अनुरोध अस्वीकार कर दिया जाता है. इस बारे में, यहां दिए गए रिस्पॉन्स दस्तावेज़ में बताया गया है.

ध्यान दें: JavaScript क्लाइंट में, ये अनुरोध CORS OPTIONS प्रीफ़्लाइट को ट्रिगर करते हैं, क्योंकि:

कॉल किए जा सकने वाले ट्रिगर, इन OPTIONS अनुरोधों को अपने-आप मैनेज करते हैं.

अनुरोध का मुख्य भाग

एचटीटीपी अनुरोध का मुख्य हिस्सा, JSON ऑब्जेक्ट होना चाहिए. इसमें इनमें से कोई एक फ़ील्ड होना चाहिए:

  • ज़रूरी: data - फ़ंक्शन में पास किया गया आर्ग्युमेंट. यह कोई भी मान्य JSON वैल्यू हो सकती है. इसे नीचे बताए गए सीरियलाइज़ेशन फ़ॉर्मैट के हिसाब से, नेटिव JavaScript टाइप में अपने-आप डिकोड कर दिया जाता है.

अगर अनुरोध में कोई अन्य फ़ील्ड मौजूद है, तो बैकएंड उसे गलत फ़ॉर्मैट वाला अनुरोध मानता है और उसे अस्वीकार कर देता है.

रिस्पॉन्स फ़ॉर्मैट: स्टेटस कोड

ऐसे कई मामले हो सकते हैं जिनमें रिस्पॉन्स में गड़बड़ियों के लिए, अलग-अलग एचटीटीपी स्टेटस कोड और स्ट्रिंग स्टेटस कोड दिख सकते हैं.

  1. client ट्रिगर होने से पहले एचटीटीपी गड़बड़ी होने पर, रिस्पॉन्स को क्लाइंट फ़ंक्शन के तौर पर मैनेज नहीं किया जाता. उदाहरण के लिए, अगर कोई क्लाइंट किसी ऐसे फ़ंक्शन को कॉल करने की कोशिश करता है जो मौजूद नहीं है, तो उसे 404 Not Found रिस्पॉन्स मिलता है.

  2. अगर क्लाइंट ट्रिगर को ट्रिगर किया जाता है, लेकिन अनुरोध गलत फ़ॉर्मैट में होता है, जैसे कि JSON में नहीं होना, अमान्य फ़ील्ड होना या data फ़ील्ड मौजूद न होना, तो अनुरोध को 400 Bad Request के साथ अस्वीकार कर दिया जाता है. साथ ही, गड़बड़ी का कोड INVALID_ARGUMENT दिखता है.

  3. अगर अनुरोध में दिया गया पुष्टि करने वाला टोकन अमान्य है, तो अनुरोध को 401 Unauthorized के साथ अस्वीकार कर दिया जाता है. साथ ही, गड़बड़ी का कोड UNAUTHENTICATED दिखता है.

  4. अगर अनुरोध में दिया गया FCM रजिस्ट्रेशन टोकन अमान्य है, तो इसकी कोई जानकारी नहीं दी जाती. हर अनुरोध पर टोकन की जांच नहीं की जाती. हालांकि, FCM की मदद से पुश नोटिफ़िकेशन भेजने के लिए, टोकन की जांच की जाती है.

  5. अगर कॉल किए जा सकने वाले ट्रिगर को ट्रिगर किया जाता है, लेकिन वह बिना मैनेज किए गए अपवाद की वजह से काम नहीं करता या कोई गड़बड़ी वाला प्रॉमिस दिखाता है, तो अनुरोध को 500 Internal Server Error के साथ अस्वीकार कर दिया जाता है. साथ ही, गड़बड़ी का कोड INTERNAL दिखाया जाता है. इससे, कोडिंग से जुड़ी गड़बड़ियां गलती से असली उपयोगकर्ताओं को दिखने से बचती हैं.

  6. अगर कॉल किए जा सकने वाले फ़ंक्शन के लिए दिए गए एपीआई का इस्तेमाल करके, कॉल किए जा सकने वाले फ़ंक्शन को कॉल किया जाता है और वह गड़बड़ी की साफ़ तौर पर जानकारी देता है, तो अनुरोध पूरा नहीं होता. एचटीटीपी स्टेटस कोड, गड़बड़ी की स्थिति को एचटीटीपी स्टेटस में आधिकारिक तौर पर मैप करने पर आधारित होता है. इस बारे में code.proto में बताया गया है. गड़बड़ी का कोड, मैसेज, और जानकारी, जवाब के मुख्य हिस्से में कोड में बदली जाती है. इस बारे में यहां बताया गया है. इसका मतलब है कि अगर फ़ंक्शन, स्टेटस OK के साथ साफ़ तौर पर गड़बड़ी दिखाता है, तो जवाब का स्टेटस 200 OK होता है. हालांकि, जवाब में error फ़ील्ड सेट होता है.

  7. क्लाइंट ट्रिगर होने पर, रिस्पॉन्स का स्टेटस 200 OK होता है.

रिस्पॉन्स का फ़ॉर्मैट: हेडर

रिस्पॉन्स में ये हेडर होते हैं:

  • Content-Type: application/json
  • ; charset=utf-8 को इस्तेमाल करने की अनुमति है. हालांकि, ऐसा करना ज़रूरी नहीं है.

जवाब का लेख

क्लाइंट एंडपॉइंट से मिलने वाला रिस्पॉन्स हमेशा JSON ऑब्जेक्ट होता है. इसमें कम से कम result या error के साथ-साथ, वैकल्पिक फ़ील्ड भी शामिल होने चाहिए. अगर रिस्पॉन्स, JSON ऑब्जेक्ट नहीं है या उसमें data या error नहीं है, तो क्लाइंट SDK को अनुरोध को Google गड़बड़ी कोड INTERNAL (13) के साथ अस्वीकार के तौर पर मार्क करना चाहिए.

  • error - अगर यह फ़ील्ड मौजूद है, तो अनुरोध को अस्वीकार माना जाता है. भले ही, एचटीटीपी स्टेटस कोड कुछ भी हो या data भी मौजूद हो. गड़बड़ियों के लिए, इस फ़ील्ड की वैल्यू, स्टैंडर्ड Google Cloud एचटीटीपी मैपिंग फ़ॉर्मैट में JSON ऑब्जेक्ट होनी चाहिए. इसमें status, message, और (ज़रूरी नहीं) details के लिए फ़ील्ड होने चाहिए. code फ़ील्ड को शामिल नहीं किया जाएगा. अगर status फ़ील्ड सेट नहीं है या इसकी वैल्यू अमान्य है, तो क्लाइंट को code.proto के मुताबिक, स्थिति को INTERNAL के तौर पर दिखाना चाहिए. अगर details मौजूद है, तो इसे क्लाइंट SDK टूल में गड़बड़ी से जुड़ी उपयोगकर्ता की जानकारी में शामिल किया जाता है. हालांकि, ऐसा तब ही किया जाता है, जब यह लागू हो.
    ध्यान दें: यहां details फ़ील्ड में उपयोगकर्ता की दी गई वैल्यू होती है. यह ज़रूरी नहीं है कि यह Google Status फ़ॉर्मैट की तरह, प्रोटो टाइप के हिसाब से की गई वैल्यू की सूची हो.
  • result - फ़ंक्शन से मिली वैल्यू. यह कोई भी मान्य JSON वैल्यू हो सकती है. firebase-functions SDK टूल, उपयोगकर्ता की दी गई वैल्यू को अपने-आप इस JSON फ़ॉर्मैट में बदल देता है. क्लाइंट SDK, नीचे बताए गए सीरियलाइज़ेशन फ़ॉर्मैट के हिसाब से, इन पैरामीटर को नेटिव टाइप में अपने-आप डिकोड कर देते हैं.

अगर अन्य फ़ील्ड मौजूद हैं, तो उन्हें अनदेखा किया जाना चाहिए.

सीरियलाइज़ेशन

अनुरोध और जवाब, दोनों के लिए डेटा पेलोड का सीरियलाइज़ेशन फ़ॉर्मैट एक जैसा होता है.

प्लैटफ़ॉर्म पर एक जैसी वैल्यू देने के लिए, इन्हें JSON में कोड में बदला जाता है. ऐसा करने के लिए, स्टैंडर्ड JSON मैपिंग का इस्तेमाल किया जाता है. ऐसा इसलिए किया जाता है, ताकि ये वैल्यू, प्रोटो3 प्रोटोकॉल बफ़र में Any फ़ील्ड की वैल्यू की तरह काम कर सकें. null, int, double या string जैसे सिंपल टाइप की वैल्यू को सीधे तौर पर एन्कोड किया जाता है. साथ ही, इनमें उनके टाइप की जानकारी शामिल नहीं होती. इसलिए, float और double को एक ही तरह से एन्क्रिप्ट किया जाता है. हो सकता है कि आपको यह पता न हो कि कॉल के दूसरे छोर पर कौनसा मिला है. JSON में काम न करने वाले टाइप के लिए, वैल्यू के तौर पर टाइप की गई proto3 एन्कोडिंग का इस्तेमाल किया जाता है. ज़्यादा जानकारी के लिए, किसी भी JSON कोडिंग के लिए दस्तावेज़ देखें.

इस तरह के विज्ञापन दिखाए जा सकते हैं:

  • null - null
  • int (साइन वाला या बिना साइन वाला, ज़्यादा से ज़्यादा 32 बिट) - उदाहरण के लिए, 3 या -30.
  • फ़्लोट - उदाहरण के लिए, 3.14
  • डबल - उदाहरण के लिए, 3.14
  • बूलियन - true या false
  • स्ट्रिंग - उदाहरण के लिए, "hello world"
  • map<string, any=""> - उदाहरण के लिए, {"x": 3}</string,>
  • list - उदाहरण के लिए, [1, 2, 3]
  • long (साइन वाला या बिना साइन वाला, ज़्यादा से ज़्यादा 64 बिट) - [ज़्यादा जानकारी के लिए नीचे देखें]

float और double के लिए, NaN और Infinity वैल्यू का इस्तेमाल नहीं किया जा सकता.

ध्यान दें कि long एक खास टाइप है, जिसे आम तौर पर JSON में इस्तेमाल करने की अनुमति नहीं है. हालांकि, इसे proto3 स्पेसिफ़िकेशन में शामिल किया गया है. उदाहरण के लिए, इन्हें इस तरह से कोड में बदला जाता है:

लंबा

{
    '@type': 'type.googleapis.com/google.protobuf.Int64Value',
    'value': '-123456789123456'
}

बिना साइन वाला लंबा

{
    '@type': 'type.googleapis.com/google.protobuf.UInt64Value',
    'value': '123456789123456'
}

आम तौर पर, @type कुंजी को रिज़र्व माना जाना चाहिए और इसे पास किए गए मैप के लिए इस्तेमाल नहीं किया जाना चाहिए.

सिंपल टाइप के लिए टाइप तय नहीं किया गया है. इसलिए, कुछ वैल्यू को वायर पर भेजने के बाद, उनका टाइप बदल जाएगा. पास किए गए float को double में बदल दिया जाता है. short, int हो जाता है. इसी तरह, आगे की दर भी इसी हिसाब से तय होगी. Android में, सूची की वैल्यू के लिए List और JSONArray, दोनों का इस्तेमाल किया जा सकता है. ऐसे मामलों में, JSONArray को पास करने पर List मिलेगा.

अगर किसी ऐसे मैप को डीसीरीयलाइज़ किया जाता है जिसमें @type फ़ील्ड मौजूद नहीं है, तो उसे मैप के तौर पर ही छोड़ दिया जाता है. इससे डेवलपर, पुराने क्लाइंट को नुकसान पहुंचाए बिना, अपनी रिटर्न वैल्यू में नए टाइप के फ़ील्ड जोड़ सकते हैं.

कोड सैंपल

इस सेक्शन में दिए गए सैंपल से, इन चीज़ों को कोड में बदलने का तरीका पता चलता है:

  • Swift में callable.call का उदाहरण
  • कॉल के लिए सफलता का जवाब
  • कॉल के लिए गड़बड़ी का जवाब

कोड में बदलने के लिए, Swift में Callable.call का उदाहरण

callable.call([
    "aString": "some string",
    "anInt": 57,
    "aFloat": 1.23,
    "aLong": -123456789123456 as Int64
])

अनुरोध का हेडर:

Method: POST
Content-Type: application/json; charset=utf-8
Authorization: Bearer some-auth-token
Firebase-Instance-ID-Token: some-iid-token

अनुरोध का मुख्य हिस्सा:

{
    "data": {
        "aString": "some string",
        "anInt": 57,
        "aFloat": 1.23,
        "aLong": {
            "@type": "type.googleapis.com/google.protobuf.Int64Value",
            "value": "-123456789123456"
        }
    }
}

Response to encode

return {
    "aString": "some string",
    "anInt": 57,
    "aFloat": 1.23
};

सफल रिस्पॉन्स हेडर:

200 OK
Content-Type: application/json; charset=utf-8

सफल रिस्पॉन्स बॉडी:

{
    "response": {
        "aString": "some string",
        "anInt": 57,
        "aFloat": 1.23
    }
}

कोड में बदलने में हुई गड़बड़ी

throw new HttpsError("unauthenticated", "Request had invalid credentials.", {
  "some-key": "some-value"
});

रिस्पॉन्स हेडर काम नहीं कर रहा है:

401 UNAUTHENTICATED
Content-Type: application/json; charset=utf-8

जवाब का मुख्य हिस्सा नहीं मिला:

{
    "error": {
        "message": "Request had invalid credentials.",
        "status": "UNAUTHENTICATED",
        "details": {
            "some-key": "some-value"
        }
    }
}