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

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

تنسيق الطلب: العناوين

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

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

وفي حال تضمين أي رؤوس أخرى، يتم رفض الطلب، كما هو موضّح في مستندات الرد أدناه.

ملاحظة: في برامج JavaScript، تؤدّي هذه الطلبات إلى تشغيل الطلب الأولي لسياسة CORS OPTIONS للأسباب التالية:

  • لا يُسمح باستخدام application/json. يجب أن يكون text/plain أو application/x-www-form-urlencoded.
  • العنوان Authorization ليس عنوان طلب مُدرَج في قائمة CORS-آمن.
  • وبالمثل، لا يُسمح باستخدام عناوين أخرى.

يعالج المُشغِّل القابل للاستدعاء طلبات 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. وإذا كان الرمز المميّز للتسجيل في خدمة "المراسلة عبر السحابة الإلكترونية من Firebase" المقدَّم في الطلب غير صالح، سيصبح السلوك غير معروف. لا يتم التحقّق من الرمز المميّز في كل طلب، إلا إذا تم استخدامه لإرسال إشعار فوري من خلال خدمة "المراسلة عبر السحابة الإلكترونية من Firebase".

  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 العادي بحثًا عن الأخطاء، مع حقول للأخطاء 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"
  • خريطة<string, any=""> - مثال: {"x": 3}</string,>
  • قائمة - مثال: [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 في Swift
  • استجابة ناجحة للمكالمة
  • تعذّر الرد على المكالمة

مثال على 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"
        }
    }
}