مواصفات بروتوكول https.onCall

مشغل https.onCall للوظائف السحابية هو مشغل HTTPS بتنسيق محدد للطلب والاستجابة. يوفر هذا القسم مواصفات لطلب HTTPS وتنسيقات الاستجابة التي يستخدمها العميل SDKs لتنفيذ واجهة برمجة التطبيقات (API). قد تكون هذه المعلومات مفيدة لك إذا تعذر تلبية متطلباتك باستخدام أنظمة Android أو Apple أو مجموعات SDK للويب.

تنسيق الطلب: الرؤوس

يجب أن يكون طلب HTTP إلى نقطة نهاية المشغل القابلة للاستدعاء عبارة عن POST بالرؤوس التالية:

  • مطلوب: Content-Type: application/json
    • اختياري ; charset=utf-8 مسموح بها.
  • اختياري: Authorization: Bearer <token>
    • رمز معرف مستخدم مصادقة Firebase للمستخدم الذي قام بتسجيل الدخول والذي يقدم الطلب. تتحقق الواجهة الخلفية تلقائيًا من هذا الرمز المميز وتجعله متاحًا في context المعالج. إذا كان الرمز غير صالح، فسيتم رفض الطلب.
  • اختياري: Firebase-Instance-ID-Token: <iid>
    • رمز تسجيل FCM من حزمة SDK لعميل Firebase. يجب أن يكون هذا سلسلة. هذا متاح في context المعالج. يتم استخدامه لاستهداف إشعارات الدفع.
  • اختياري: X-Firebase-AppCheck: <token>
    • رمز Firebase App Check المميز الذي يقدمه تطبيق العميل الذي يقدم الطلب. تتحقق الواجهة الخلفية تلقائيًا من هذا الرمز المميز وتفك تشفيره، عن طريق إدخال appId في context المعالج. إذا تعذر التحقق من الرمز المميز، فسيتم رفض الطلب. (متوفر لـ SDK >=3.14.0)

إذا تم تضمين أي رؤوس أخرى، فسيتم رفض الطلب، كما هو موضح في وثائق الاستجابة أدناه.

ملاحظة: في عملاء JavaScript، تؤدي هذه الطلبات إلى تشغيل الاختبار المبدئي لـ CORS OPTIONS ، للأسباب التالية:

يعالج المشغل القابل للاستدعاء طلبات OPTIONS هذه تلقائيًا.

هيئة الطلب

يجب أن يكون نص طلب HTTP عبارة عن كائن JSON يحتوي على أي من الحقول التالية:

  • مطلوب: data - الوسيطة التي تم تمريرها إلى الوظيفة. يمكن أن تكون هذه أي قيمة JSON صالحة. يتم فك تشفير هذا تلقائيًا إلى أنواع JavaScript أصلية وفقًا لتنسيق التسلسل الموضح أدناه.

إذا كانت هناك أي حقول أخرى موجودة في الطلب، فإن الواجهة الخلفية تعتبر الطلب غير صحيح، ويتم رفضه.

تنسيق الاستجابة: رموز الحالة

هناك العديد من الحالات التي قد تؤدي إلى رموز حالة HTTP مختلفة ورموز حالة سلسلة للأخطاء في الاستجابة.

  1. في حالة حدوث خطأ HTTP قبل استدعاء مشغل 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. إذا تم استدعاء الكائن القابل للاستدعاء وإرجاع حالة خطأ صريحة باستخدام واجهة برمجة التطبيقات المتوفرة للوظائف القابلة للاستدعاء، فسيفشل الطلب. يعتمد رمز حالة HTTP الذي تم إرجاعه على التعيين الرسمي لحالة الخطأ إلى حالة HTTP، كما هو محدد في 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 - إذا كان هذا الحقل موجودًا، فسيتم اعتبار الطلب فاشلاً، بغض النظر عن رمز حالة HTTP أو ما إذا كانت data موجودة أيضًا. يجب أن تكون قيمة هذا الحقل عبارة عن كائن JSON بتنسيق Google Cloud HTTP Mapping القياسي للأخطاء، مع حقول status message details (اختياريًا). لا ينبغي تضمين حقل code . إذا كان حقل status غير محدد، أو كان قيمة غير صالحة، فيجب على العميل التعامل مع الحالة على أنها INTERNAL ، وفقًا لـ code.proto . إذا كانت details موجودة، فسيتم تضمينها في أي معلومات مستخدم مرفقة بالخطأ في SDK للعميل، إن أمكن.
    ملاحظة: حقل details هنا عبارة عن قيمة مقدمة من المستخدم. إنها ليست بالضرورة قائمة من القيم التي يتم مفتاحها حسب النوع الأولي كما هو الحال في تنسيق Status Google.
  • result - القيمة التي يتم إرجاعها بواسطة الدالة. يمكن أن تكون هذه أي قيمة JSON صالحة. تقوم حزمة SDK لوظائف firebase تلقائيًا بتشفير القيمة التي أرجعها المستخدم إلى تنسيق JSON هذا. تقوم حزم SDK للعميل تلقائيًا بفك تشفير هذه المعلمات إلى أنواع أصلية وفقًا لتنسيق التسلسل الموضح أدناه.

في حالة وجود حقول أخرى، يجب تجاهلها.

التسلسل

تنسيق التسلسل لحمولات البيانات العشوائية هو نفسه لكل من الطلب والاستجابة.

من أجل تناسق النظام الأساسي، يتم ترميزها في JSON كما لو كانت قيمة Any حقل في المخزن المؤقت لبروتوكول proto3، باستخدام تعيين JSON القياسي . يتم ترميز قيم الأنواع البسيطة مثل null أو int أو double أو string مباشرةً، ولا تتضمن نوعها الصريح. لذا، يتم تشفير float double بنفس الطريقة، وقد لا تعرف أيهما يتم استقباله على الطرف الآخر من المكالمة. بالنسبة للأنواع التي ليست أصلية في JSON، يتم استخدام تشفير proto3 المكتوب للقيمة. لمزيد من المعلومات، راجع الوثائق الخاصة بأي ترميز JSON .

يُسمح بالأنواع التالية:

  • null
  • int (موقع أو غير موقع، حتى 32 بت) - على سبيل المثال 3 أو -30 .
  • تعويم - على سبيل المثال 3.14
  • مزدوج - على سبيل المثال 3.14
  • منطقية - true أو false
  • سلسلة - على سبيل المثال "hello world"
  • خريطة - على سبيل المثال {"x": 3}
  • قائمة - على سبيل المثال [1, 2, 3]
  • طويل (موقع أو غير موقع، حتى 64 بت) - [انظر أدناه للحصول على التفاصيل]

لا يتم دعم قيم NaN و Infinity الخاصة float double .

لاحظ أن 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 غير معروف، فسيتم تركها كخريطة. يتيح ذلك للمطورين إضافة حقول بأنواع جديدة إلى قيم الإرجاع الخاصة بهم دون فصل العملاء الأقدم.

عينات التعليمات البرمجية

توضح العينات الموجودة في هذا القسم كيفية تشفير ما يلي:

  • مثال callable.call في سويفت
  • استجابة ناجحة للدعوة
  • فشل الاستجابة للمكالمة

مثال Callable.call في Swift للتشفير

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"
        }
    }
}

الرد على التشفير

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"
        }
    }
}