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

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

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

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

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

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

ملاحظة: في برامج 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، يجب أن يتعامل IDE للعميل مع الطلب على أنّه تعذّر برمز الخطأ INTERNAL (13) من Google.

  • error: في حال توفّر هذا الحقل، سيتم اعتبار الطلب غير صحيح، بغض النظر عن رمز حالة HTTP أو ما إذا كان data متوفّرًا أيضًا. يجب أن تكون قيمة هذا الحقل عنصرًا في تنسيق 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 المكتوب للقيمة. لمزيد من المعلومات، اطّلِع على مستندات ترميز Any 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"
        }
    }
}