معالجة أخطاء المشرف SDK

تنقسم أخطاء SDK للمشرف إلى فئتين:

  1. أخطاء البرمجة: هي أخطاء البرمجة والتكوين في تطبيق المستخدم. تحدث هذه الأخطاء في الغالب بسبب الاستخدام غير الصحيح لـ SDK (مثل تمرير قيمة null إلى طريقة لا تقبل القيم null )، وأخطاء التكوين الأخرى على مستوى مشروع Firebase أو SDK (بيانات الاعتماد المفقودة، وسلسلة معرف المشروع غير الصحيحة، وما إلى ذلك) على).
  2. أخطاء واجهة برمجة التطبيقات (API): تتضمن هذه الأخطاء العديد من الأخطاء القابلة للاسترداد التي تحدث أثناء تنفيذ SDK، وجميع الأخطاء التي تنشأ في خدمات الواجهة الخلفية لـ Firebase، والأخطاء العابرة الأخرى (مثل انتهاء المهلات) التي قد تحدث أثناء إجراء مكالمات RPC.

تشير Admin SDK إلى أخطاء البرمجة عن طريق ظهور خطأ أصلي في النظام الأساسي المعني.

  • Java: يرمي مثيلات IllegalArgumentException أو NullPointerException أو أي نوع خطأ مدمج مماثل في وقت التشغيل.
  • Python: رفع مثيلات ValueError أو TypeError أو أي نوع آخر من الأخطاء المضمنة.
  • Go: إرجاع خطأ عام.
  • .NET: يرمي مثيلات ArgumentException أو ArgumentNullException أو أي نوع خطأ مدمج مماثل.

في معظم المواقف، لا ينبغي عليك التعامل بشكل صريح مع أخطاء البرمجة. بدلاً من ذلك، يجب عليك إصلاح التعليمات البرمجية والتكوين الخاص بك لتجنب أخطاء البرمجة تمامًا. خذ بعين الاعتبار مقتطف Java التالي:

String uid = getUserInput();

UserRecord user = FirebaseAuth.getInstance().getUser(uid);

إذا قام الأسلوب getUserInput() بإرجاع سلاسل null أو فارغة، فستطرح واجهة برمجة التطبيقات FirebaseAuth.getUser() API IllegalArgumentException . بدلاً من معالجتها بشكل صريح، يمكنك التخفيف من المشكلة عن طريق التأكد من أن أسلوب getUserInput() لا يُرجع مطلقًا سلسلة UID غير صالحة. إذا لم يكن ذلك ممكنًا، فقم بتنفيذ التحقق من الوسيطة اللازمة في التعليمات البرمجية الخاصة بك على النحو التالي:

String uid = getUserInput();
if (Strings.isNullOrEmpty(uid)) {
    log.warn("UID must not be null or empty");
    return;
}

UserRecord user = FirebaseAuth.getInstance().getUser(uid);

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

عادةً ما يركز الجزء الأكبر من جهود معالجة الأخطاء على معالجة أخطاء واجهة برمجة التطبيقات (API) . بعض هذه الأخطاء قابلة للاسترداد، مثل الأخطاء التي نتجت عن خدمة غير متاحة مؤقتًا، وبعضها يمكن توقعه أثناء تدفق تنفيذ البرنامج العادي، مثل اكتشاف رموز المعرف غير الصالحة أو منتهية الصلاحية. يوضح الجزء المتبقي من هذا الدليل كيفية تمثيل Admin SDK لأخطاء واجهة برمجة التطبيقات هذه، والخيارات المتنوعة المتاحة للتعامل معها.

هيكل خطأ API

يتكون خطأ API من المكونات التالية:

  1. خطا بالكود
  2. رسالة خطأ
  3. رمز خطأ الخدمة (اختياري)
  4. استجابة HTTP (اختياري)

نضمن أن كل خطأ في واجهة برمجة التطبيقات (API) يحتوي على رمز خطأ ورسالة خطأ. تحتوي بعض أخطاء واجهة برمجة التطبيقات (API) أيضًا على رمز خطأ خدمة خاص بواجهة برمجة التطبيقات (API) التي تسببت في حدوث الخطأ. على سبيل المثال، تحتوي بعض الأخطاء التي تم إنشاؤها بواسطة Firebase Auth API على رمز خطأ في الخدمة خاص بـ Firebase Auth. إذا كان الخطأ نتيجة استجابة خطأ HTTP من خدمة الواجهة الخلفية، فإن خطأ واجهة برمجة التطبيقات (API) يحتوي أيضًا على استجابة HTTP المقابلة. يمكن استخدام هذا لفحص الرؤوس والمحتويات الدقيقة للاستجابة الأصلية، وهو أمر مفيد لتصحيح الأخطاء أو التسجيل أو تنفيذ منطق أكثر تعقيدًا لمعالجة الأخطاء.

توفر جميع تطبيقات Admin SDK باستثناء Node.js واجهات برمجة التطبيقات التي تتيح الوصول إلى مكونات أخطاء واجهة برمجة التطبيقات المذكورة أعلاه.

أنواع الأخطاء وواجهات برمجة التطبيقات حسب اللغة

جافا

في Java، تعمل جميع أخطاء واجهة برمجة التطبيقات (API) على توسيع فئة FirebaseException . يمكنك الوصول إلى رمز الخطأ ورسالة الخطأ واستجابة HTTP الاختيارية من هذه الفئة الأساسية.

public class FirebaseException extends Exception {
    @NonNull
    public ErrorCode getErrorCode() {
        // ...
    }

    @NonNull
    public String getMessage() {
        // ...
    }

    @Nullable
    public IncomingHttpResponse getHttpResponse() {
        // ...
    }
}

توفر واجهات برمجة التطبيقات (APIs) التي تكشف رموز خطأ الخدمة فئات فرعية خاصة بواجهة برمجة التطبيقات (API) لـ FirebaseException . على سبيل المثال، تم الإعلان عن جميع الطرق العامة في FirebaseAuth API لرمي مثيلات FirebaseAuthException . يمكنك الوصول إلى رمز خطأ الخدمة من هذه الفئة المشتقة.

public class FirebaseAuthException extends FirebaseException {
    @Nullable
    public AuthErrorCode getAuthErrorCode() {
        // ...
    }
}

بايثون

في Python، تعمل جميع أخطاء واجهة برمجة التطبيقات (API) على توسيع فئة exceptions.FirebaseError . يمكنك الوصول إلى رمز الخطأ ورسالة الخطأ واستجابة HTTP الاختيارية من هذه الفئة الأساسية.

class FirebaseError(Exception):
    @property
    def code(self):
          # ...

    @property
    def message(self):
          # ...

    @property
    def http_response(self):
          # ...

علاوة على ذلك، تقدم Python Admin SDK فئات مشتقة منفصلة لكل رمز خطأ. ونحن نشير إليها على أنها فئات أخطاء النظام الأساسي .

class InvalidArgumentError(FirebaseError):
    # ...

class NotFoundError(FirebaseError):
    # ...

يمكنك إما اكتشاف FirebaseError في التعليمات البرمجية الخاصة بك والتحقق من code الخاصة به، أو إجراء فحص isinstance() مقابل فئة خطأ في النظام الأساسي. أو يمكنك كتابة تعليمات برمجية لاكتشاف أنواع أخطاء معينة في النظام الأساسي مباشرةً. من المرجح أن يؤدي النهج الأخير إلى كود معالجة الأخطاء الأكثر قابلية للقراءة.

توفر واجهات برمجة التطبيقات التي تكشف رموز خطأ الخدمة فئات فرعية خاصة بواجهة برمجة التطبيقات لفئات أخطاء النظام الأساسي. على سبيل المثال، قد تؤدي جميع الطرق العامة في وحدة auth إلى ظهور أنواع أخطاء خاصة بواجهة برمجة التطبيقات (API)، مثل auth.UserNotFoundError و auth.ExpiredIdTokenError .

class UserNotFoundError(exceptions.NotFoundError):
    # …

class ExpiredIdTokenError(exceptions.InvalidArgumentError):
    # ...

يذهب

توفر Go Admin SDK حزمة errorutils التي تحتوي على سلسلة من الوظائف التي تسمح باختبار رموز الأخطاء.

package errorutils

func IsInvalidArgument(err error) bool {
    // ...
}

func IsNotFound(err error) bool {
    // ...
}

رسالة الخطأ هي ببساطة السلسلة التي يتم إرجاعها بواسطة الدالة Error() الخاصة بالخطأ. يمكن الوصول إلى استجابة HTTP الاختيارية عن طريق استدعاء الدالة errorutils.HTTPResponse() ، والتي تقوم بإرجاع *http.Response .

من الآمن تمرير nil أو أي قيمة خطأ أخرى إلى وظائف التحقق من الأخطاء في الحزمة errorutils . فهي تُرجع true إذا كانت وسيطة الإدخال تحتوي بالفعل على رمز الخطأ المعني، وتُرجع false لكل شيء آخر. الدالة HTTPResponse() لها سلوك مشابه، باستثناء أنها تُرجع nil بدلاً من false .

توفر واجهات برمجة التطبيقات التي تكشف رموز خطأ الخدمة وظائف التحقق من الأخطاء الخاصة بواجهة برمجة التطبيقات في الحزم المقابلة. على سبيل المثال، توفر حزمة auth الوظائف IsUserNotFound() و IsExpiredIDTokenError() .

.شبكة

في .NET، تعمل جميع أخطاء واجهة برمجة التطبيقات (API) على توسيع فئة FirebaseException . يمكنك الوصول إلى رمز خطأ النظام الأساسي ورسالة الخطأ واستجابة HTTP الاختيارية من هذه الفئة الأساسية.

public class FirebaseException : Exception {

    public ErrorCode ErrorCode { get; }

    public String Message { get; }

    public HttpResponseMessage HttpResponse { get; }
}

توفر واجهات برمجة التطبيقات (APIs) التي تكشف رموز خطأ الخدمة فئات فرعية خاصة بواجهة برمجة التطبيقات (API) لـ FirebaseException . على سبيل المثال، تم الإعلان عن جميع الأساليب العامة في FirebaseAuth API لطرح مثيلات FirebaseAuthException . يمكنك الوصول إلى رمز خطأ الخدمة من هذه الفئة المشتقة.

public class FirebaseAuthException : FirebaseException {

    public AuthErrorCode AuthErrorCode { get; }
}

رموز خطأ النظام الأساسي

تعد رموز الأخطاء شائعة عبر جميع خدمات Firebase وGoogle Cloud Platform. يوضح الجدول التالي جميع رموز الأخطاء المحتملة في النظام الأساسي. وهذه قائمة مستقرة، ومن المتوقع أن تظل دون تغيير لفترة طويلة.

سيطة غير صالحة حدد العميل وسيطة غير صالحة.
فشل_الشروط المسبقة لا يمكن تنفيذ الطلب في حالة النظام الحالية، مثل حذف دليل غير فارغ.
خارج النطاق حدد العميل نطاقًا غير صالح.
غير مصادق عليه لم تتم مصادقة الطلب بسبب فقدان رمز OAuth المميز أو غير صالح أو منتهي الصلاحية.
تم رفض الإذن ليس لدى العميل الإذن الكافي. يمكن أن يحدث هذا لأن رمز OAuth المميز لا يحتوي على النطاقات الصحيحة، أو ليس لدى العميل إذن، أو لم يتم تمكين واجهة برمجة التطبيقات لمشروع العميل.
غير معثور عليه لم يتم العثور على المورد المحدد، أو تم رفض الطلب لأسباب غير معلنة مثل القائمة البيضاء.
صراع تعارض التزامن، مثل تعارض القراءة والتعديل والكتابة. يتم استخدامه فقط بواسطة عدد قليل من الخدمات القديمة. تستخدم معظم الخدمات ABORTED أو ALREADY_EXISTS بدلاً من ذلك. ارجع إلى الوثائق الخاصة بالخدمة لمعرفة أي منها يجب التعامل معه في التعليمات البرمجية الخاصة بك.
تم الإجهاض تعارض التزامن، مثل تعارض القراءة والتعديل والكتابة.
موجود أصلا المورد الذي حاول العميل إنشاءه موجود بالفعل.
الموارد_مستنفدة إما خارج حصة الموارد أو الوصول إلى الحد الأقصى للمعدل.
ألغيت تم إلغاء الطلب من قبل العميل.
فقدان البيانات فقدان البيانات غير القابلة للاسترداد أو تلف البيانات. يجب على العميل الإبلاغ عن الخطأ للمستخدم.
مجهول خطأ غير معروف في الخادم. عادةً ما يكون هناك خطأ في الخادم.

يتم أيضًا تعيين رمز الخطأ هذا لأخطاء تحليل الاستجابة المحلية (إلغاء التنظيم)، ومجموعة واسعة من أخطاء الإدخال/الإخراج الأخرى ذات المستوى المنخفض والتي لا يمكن تشخيصها بسهولة.

داخلي خطأ في الخادم الداخلي. عادةً ما يكون هناك خطأ في الخادم.
غير متوفره الخدمة غير متوفرة. عادةً ما يكون الخادم معطلاً مؤقتًا.

يتم أيضًا تعيين رمز الخطأ هذا لأخطاء الشبكة المحلية (تم رفض الاتصال، لا يوجد طريق للمضيف).

DEADLINE_EXCEEDED لقد تجاوز الموعد النهائي للطلب. لن يحدث هذا إلا إذا قام المتصل بتعيين موعد نهائي أقصر من الموعد النهائي الافتراضي لواجهة برمجة التطبيقات الهدف (أي الموعد النهائي المطلوب لا يكفي للخادم لمعالجة الطلب)، ولم ينته الطلب خلال الموعد النهائي.

يتم أيضًا تعيين رمز الخطأ هذا للاتصال المحلي ومهلة القراءة.

يمكن أن تؤدي معظم واجهات برمجة التطبيقات (APIs) فقط إلى مجموعة فرعية من رموز الخطأ المذكورة أعلاه. على أية حال، ليس من المتوقع منك أن تتعامل بشكل صريح مع كل رموز الأخطاء هذه عند تنفيذ معالجات الأخطاء الخاصة بك. ستهتم معظم التطبيقات فقط برموز خطأ محددة واحدة أو اثنين وتتعامل مع كل شيء آخر على أنه فشل عام وغير قابل للاسترداد.

رموز الخطأ الخاصة بالخدمة

مصادقة Firebase

CERTIFICATE_FETCH_FAILED فشل جلب شهادات المفتاح العام المطلوبة للتحقق من JWT (رمز المعرف أو ملف تعريف ارتباط الجلسة).
البريد الالكتروني موجود بالفعل يوجد مستخدم بالفعل مع البريد الإلكتروني المقدم.
EXPIRED_ID_TOKEN انتهت صلاحية رمز المعرف المحدد للتحقق من verifyIdToken() .
EXPIRED_SESSION_COOKIE انتهت صلاحية ملف تعريف ارتباط الجلسة المحدد verifySessionCookie() .
INVALID_DYNAMIC_LINK_DOMAIN لم يتم تكوين مجال الارتباط الديناميكي المقدم أو ترخيصه للمشروع الحالي. ذات صلة بواجهات برمجة تطبيقات رابط إجراء البريد الإلكتروني.
INVALID_ID_TOKEN رمز المعرف المحدد لـ verifyIdToken() غير صالح.
INVALID_SESSION_COOKIE ملف تعريف ارتباط الجلسة المحدد verifySessionCookie() غير صالح.
PHONE_NUMBER_ALREADY_EXISTS يوجد مستخدم بالفعل برقم الهاتف المقدم.
REVOKED_ID_TOKEN تم إبطال رمز المعرف المحدد للتحقق verifyIdToken() .
REVOKED_SESSION_COOKIE انتهت صلاحية ملف تعريف ارتباط الجلسة المحدد verifySessionCookie() .
UNAUTHORIZED_CONTINUE_URL نطاق عنوان URL للمتابعة غير مدرج في القائمة البيضاء. ذات صلة بواجهات برمجة تطبيقات رابط إجراء البريد الإلكتروني.
لم يتم العثور على المستخدم لم يتم العثور على سجل مستخدم للمعرف المحدد.

المراسلة السحابية من Firebase

THIRD_PARTY_AUTH_ERROR شهادة APNs أو مفتاح API لمصادقة دفع الويب غير صالح أو مفقود.
سيطة غير صالحة هناك وسيطة واحدة أو أكثر محددة في الطلب غير صالحة.
داخلي خطأ في الخادم الداخلي.
حصة تجاوزت تم تجاوز حد الإرسال لهدف الرسالة.
SENDER_ID_MISMATCH يختلف معرف المرسل المصادق عليه عن معرف المرسل الخاص برمز التسجيل. وهذا يعني عادةً أن المرسل ورمز التسجيل المستهدف ليسا في نفس مشروع Firebase.
غير متوفره خدمة المراسلة السحابية غير متاحة مؤقتًا.
غير مسجل تم إلغاء تسجيل مثيل التطبيق من FCM. ويعني هذا عادةً أن الرمز المميز لتسجيل الجهاز المستخدم لم يعد صالحًا ويجب استخدام رمز جديد.

إعادة المحاولة التلقائية

تقوم Admin SDK تلقائيًا بإعادة محاولة بعض الأخطاء قبل كشف هذه الأخطاء للمستخدمين. بشكل عام، تتم إعادة محاولة أنواع الأخطاء التالية بشفافية:

  • جميع أخطاء واجهة برمجة التطبيقات (API) الناتجة عن استجابات HTTP 503 (الخدمة غير متاحة).
  • بعض أخطاء API الناتجة عن استجابات HTTP 500 (خطأ داخلي في الخادم).
  • معظم أخطاء الإدخال/الإخراج ذات المستوى المنخفض (تم رفض الاتصال، أو إعادة تعيين الاتصال، وما إلى ذلك).

سيعيد SDK محاولة كل خطأ من الأخطاء المذكورة أعلاه حتى 5 مرات (المحاولة الأصلية + 4 مرات إعادة المحاولة) مع التراجع الأسي. يمكنك تنفيذ آليات إعادة المحاولة الخاصة بك على مستوى التطبيق إذا كنت تريد ذلك، ولكن هذا غير مطلوب عادةً.

إعادة المحاولة-بعد الدعم

تأتي تطبيقات Go و.NET الخاصة بـ Admin SDK مع دعم للتعامل مع رأس HTTP Retry-After . أي أنه إذا كانت استجابة الخطأ التي أرسلتها خوادم الواجهة الخلفية تحتوي على رأس Retry-After القياسي، فسوف تحترم SDK ذلك عند إعادة المحاولة طالما أن مدة الانتظار المحددة ليست طويلة جدًا. إذا كان رأس Retry-After يشير إلى مدة انتظار طويلة جدًا، فسوف يتجاوز SDK عمليات إعادة المحاولة ويلقي خطأ واجهة برمجة التطبيقات (API) المناسب.

لا يدعم Python Admin SDK حاليًا رأس Retry-After ، ويدعم فقط التراجع الأسي البسيط.

أمثلة على معالجة أخطاء واجهة برمجة التطبيقات

تنفيذ معالج الأخطاء العام

في معظم الحالات، ما تريده هو معالج أخطاء عام يلتقط نطاقًا واسعًا من الأخطاء لمنع الإنهاء غير المتوقع لتدفق البرنامج بسبب خطأ في واجهة برمجة التطبيقات (API). عادةً ما تقوم معالجات الأخطاء هذه بتسجيل الأخطاء لأغراض التدقيق، أو استدعاء بعض إجراءات معالجة الأخطاء الافتراضية الأخرى لجميع أخطاء واجهة برمجة التطبيقات (API) التي تمت مواجهتها. إنهم ليسوا مهتمين بالضرورة برموز الخطأ المختلفة أو الأسباب التي قد تكون سببت الخطأ.

جافا

try {
  FirebaseToken token = FirebaseAuth.getInstance().verifyIdToken(idToken);
  performPrivilegedOperation(token.getUid());
} catch (FirebaseAuthException ex) {
  System.err.println("Failed to verify ID token: " + ex.getMessage());
}

بايثون

try:
  token = auth.verify_id_token(idToken)
  perform_privileged_pperation(token.uid)
except exceptions.FirebaseError as ex:
  print(f'Failed to verify ID token: {ex}')

يذهب

token, err := client.VerifyIDToken(ctx, idToken)
if err != nil {
  log.Printf("Failed to verify ID token: %v", err)
  return
}

performPrivilegedOperation(token)

.شبكة

try
{
  var token = await FirebaseAuth.DefaultInstance.VerifyIdTokenAsync(idToken);
  PerformPrivilegedOperation(token.getUid());
}
catch (FirebaseAuthException ex) 
{
  Conole.WriteLine($"Failed to verify ID token: {ex.Message}");
}

التحقق من رموز الخطأ

في بعض الحالات، قد ترغب في فحص رموز الخطأ الدقيقة، واستدعاء إجراءات مختلفة لمعالجة الأخطاء مع مراعاة السياق. في المثال التالي، لدينا معالج أخطاء يقوم بتسجيل المزيد من رسائل الخطأ المحددة بناءً على رمز خطأ الخدمة.

جافا

try {
  FirebaseToken token = FirebaseAuth.getInstance().verifyIdToken(idToken);
  performPrivilegedOperation(token.getUid());
} catch (FirebaseAuthException ex) {
  if (ex.getAuthErrorCode() == AuthErrorCode.ID_TOKEN_EXPIRED) {
    System.err.println("ID token has expired");
  } else if (ex.getAuthErrorCode() == AuthErrorCode.ID_TOKEN_INVALID) {
    System.err.println("ID token is malformed or invalid");
  } else {
    System.err.println("Failed to verify ID token: " + ex.getMessage());
  }
}

بايثون

try:
  token = auth.verify_id_token(idToken)
  perform_privileged_operation(token.uid)
except auth.ExpiredIdTokenError:
  print('ID token has expired')
except auth.InvalidIdTokenError:
  print('ID token is malformed or invalid')
except exceptions.FirebaseError as ex:
  print(f'Failed to verify ID token: {ex}')

يذهب

token, err := client.VerifyIDToken(ctx, idToken)
if auth.IsIDTokenExpired(err) {
  log.Print("ID token has expired")
  return
}
if auth.IsIDTokenInvalid(err) {
  log.Print("ID token is malformed or invalid")
  return
}
if err != nil {
  log.Printf("Failed to verify ID token: %v", err)
  return
}

performPrivilegedOperation(token)

.شبكة

try
{
  var token = await FirebaseAuth.DefaultInstance.VerifyIdTokenAsync(idToken);
  PerformPrivilegedOperation(token.getUid());
}
catch (FirebaseAuthException ex)
{
  if (ex.AuthErrorCode == AuthErrorCode.ExpiredIdToken)
  {
    Console.WriteLine("ID token has expired");
  }
  else if (ex.AuthErrorCode == AuthErrorCode.InvalidIdToken)
  {
    Console.WriteLine("ID token is malformed or invalid");
  }
  else
  {
    Conole.WriteLine($"Failed to verify ID token: {ex.Message}");
  }
}

إليك مثال آخر حيث نتحقق من رموز أخطاء المستوى الأعلى والخدمة:

جافا

try {
  FirebaseMessaging.getInstance().send(createMyMessage());
} catch (FirebaseMessagingException ex){
  if (ex.getMessagingErrorCode() == MessagingErrorCode.UNREGISTERED) {
    System.err.println("App instance has been unregistered");
    removeTokenFromDatabase();
  } else if (ex.getErrorCode() == ErrorCode.Unavailable) {
    System.err.println("FCM service is temporarily unavailable");
    scheduleForRetryInAnHour();
  } else {
    System.err.println("Failed to send notification: " + ex.getMessage());
  }
}

بايثون

try:
  messaging.send(create_my_message())
except messaging.UnregisteredError:
  print('App instance has been unregistered')
  remove_token_from_database()
except exceptions.UnavailableError:
  print('FCM service is temporarily unavailable')
  schedule_for_retry_in_an_hour()
except exceptions.FirebaseError as ex:
  print(f'Failed to send notification: {ex}')

يذهب

_, err := client.Send(ctx, createMyMessage())
if messaging.IsUnregistered(err) {
  log.Print("App instance has been unregistered")
  removeTokenFromDatabase()
  return
}
if errorutils.IsUnavailable(err) {
  log.Print("FCM service is temporarily unavailable")
  scheduleForRetryInAnHour()
  return
}
if err != nil {
  log.Printf("Failed to send notification: %v", err)
  return
}

.شبكة

try
{
  await FirebaseMessaging.DefaultInstance.SendAsync(createMyMessage());
}
catch (FirebaseMessagingException ex)
{
  if (ex.MessagingErrorCode == MessagingErrorCode.UNREGISTERED)
  {
    Console.WriteLine("App instance has been unregistered");
    removeTokenFromDatabase();
  }
  else if (ex.ErrorCode == ErrorCode.Unavailable)
  {
    Console.WriteLine("FCM service is temporarily unavailable");
    scheduleForRetryInAnHour();
  }
  else
  {
    Console.WriteLine($"Failed to send notification: {ex.Message}");
  }
}

الوصول إلى استجابة HTTP

في بعض الحالات النادرة، قد ترغب في فحص استجابة خطأ HTTP التي تم إرجاعها بواسطة خدمة الواجهة الخلفية وتنفيذ بعض إجراءات معالجة الأخطاء عليها. يكشف Admin SDK عن رؤوس ومحتويات استجابات الأخطاء هذه. عادةً ما يتم إرجاع محتوى الاستجابة كسلسلة أو تسلسل بايت خام، ويمكن تحليله إلى أي تنسيق هدف ضروري.

جافا

try {
  FirebaseMessaging.getInstance().send(createMyMessage());
} catch (FirebaseMessagingException ex){
  IncomingHttpResponse response = ex.getHttpResponse();
  if (response != null) {
    System.err.println("FCM service responded with HTTP " + response.getStatusCode());

    Map<String, Object> headers = response.getHeaders();
    for (Map.Entry<String, Object> entry : headers.entrySet()) {
      System.err.println(">>> " + entry.getKey() + ": " + entry.getValue());
    }

    System.err.println(">>>");
    System.err.println(">>> " + response.getContent());
  }
}

بايثون

try:
  messaging.send(create_my_message())
except exceptions.FirebaseError as ex:
  response = ex.http_response
  if response is not None:
    print(f'FCM service responded with HTTP {response.status_code}')

    for key, value in response.headers.items():
      print(f'>>> {key}: {value}')

    print('>>>')
    print(f'>>> {response.content}')

يذهب

_, err := client.Send(ctx, createMyMessage())
if resp := errorutils.HTTPResponse(err); resp != nil {
  log.Printf("FCM service responded with HTTP %d", resp.StatusCode)

  for key, value := range resp.Header {
      log.Printf(">>> %s: %v", key, value)
  }

  defer resp.Body.Close()
  b, _ := ioutil.ReadAll(resp.Body)
  log.Print(">>>")
  log.Printf(">>> %s", string(b))

  return
}

.شبكة

try
{
  await FirebaseMessaging.DefaultInstance.SendAsync(createMyMessage());
}
catch (FirebaseMessagingException ex)
{
  var response = ex.HttpResponse
  if response != null
  {
    Console.WriteLine($"FCM service responded with HTTP { response.StatusCode}");

    var headers = response.Headers;
    for (var entry in response.Headers)
    {
      Console.WriteLine($">>> {entry.Key}: {entry.Value}");
    }

    var body = await response.Content.ReadAsString();
    Console.WriteLine(">>>");
    Console.WriteLine($">>> {body}");
  }
}