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

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

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

تُشير حزمة تطوير البرامج (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() الخطأ 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);

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

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

بنية خطأ واجهة برمجة التطبيقات

يتألف خطأ واجهة برمجة التطبيقات من المكوّنات التالية:

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

يمكن ضمان احتواء كل خطأ في واجهة برمجة التطبيقات على رمز خطأ ورسالة خطأ. تتضمّن بعض أخطاء واجهة برمجة التطبيقات أيضًا رمز خطأ خاص بواجهة برمجة التطبيقات. الذي أدى إلى ظهور الخطأ. على سبيل المثال، بعض الأخطاء الناتجة عن مصادقة Firebase تحتوي واجهة برمجة التطبيقات على رمز خطأ في الخدمة يخصّ مصادقة Firebase. إذا حدث الخطأ نتيجة لاستجابة خطأ HTTP من إحدى خدمات الخلفية، فإن الخطأ في واجهة برمجة التطبيقات يحتوي أيضًا على استجابة HTTP المقابلة. ويمكن استخدامه لفحص عناوين ومحتويات الرد الأصلية الدقيقة، وهو أمر مفيد تصحيح الأخطاء أو التسجيل أو تنفيذ منطق أكثر تعقيدًا في التعامل مع الأخطاء.

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

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

جافا

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

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

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

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

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

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

Python

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

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

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

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

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

class InvalidArgumentError(FirebaseError):
    # ...

class NotFoundError(FirebaseError):
    # ...

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

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

class UserNotFoundError(exceptions.NotFoundError):
    # …

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

انتقال

توفّر حزمة تطوير البرامج (SDK) لمشرف Go حزمة 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

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

public class FirebaseException : Exception {

    public ErrorCode ErrorCode { get; }

    public String Message { get; }

    public HttpResponseMessage HttpResponse { get; }
}

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

public class FirebaseAuthException : FirebaseException {

    public AuthErrorCode AuthErrorCode { get; }
}

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

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

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

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

للاستخدام الداخلي حدث خطأ في الخادم الداخلي. عادةً ما يكون ذلك خطأ في الخادم.
معلومات غير متوفرة الخدمة غير متاحة. عادةً ما يكون الخادم معطلاً بشكل مؤقت.

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

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

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

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

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

Firebase Auth

CERTIFICATE_FETCH_تعذّر تعذّر استرجاع شهادات المفتاح العام المطلوبة للتحقّق من JWT (الرمز المميّز للمعرّف أو ملف تعريف ارتباط الجلسة).
البريد الإلكتروني EMAIL_ALREADY_EXISTS هناك مستخدم يمتلك عنوان البريد الإلكتروني الذي تم تقديمه.
انتهت صلاحية المعرّف الضريبي انتهت صلاحية الرمز المميّز للمعرّف الذي تم تحديده لـ verifyIdToken().
انتهت صلاحية ملف تعريف الارتباط EXPIRED_SESSION_COOKIE انتهت صلاحية ملف تعريف الارتباط للجلسة المحدّد في verifySessionCookie() 2.
ضياء_DYNAMIC_LINK_DOMAIN لم يتم إعداد نطاق الرابط الديناميكي المقدَّم أو السماح به للمشروع الحالي. ذو صلة بواجهات برمجة تطبيقات رابط إجراء البريد الإلكتروني.
معرّف_الرمز المميّز غير صالح الرمز المميّز لرقم التعريف المحدّد للمعرّف verifyIdToken() غير صالح.
ملف_تعريف_البحث_غير_الأساسي ملف تعريف الارتباط للجلسة المحدّد للحقل "verifySessionCookie()" غير صالح.
PHONE_NUMBER_ALREADY_EXISTS هناك مستخدم يمتلك رقم الهاتف المقدّم.
REVOKED_ID_TOKEN تم إبطال الرمز المميّز للمعرّف الذي تم تحديده لـ verifyIdToken().
REVOKED_SESSION_COOKIE انتهت صلاحية ملف تعريف الارتباط الخاص بالجلسة المُحدّد في verifySessionCookie().
UNAUTHORIZED_مرتبط_URL نطاق عنوان URL للمتابعة غير مضاف إلى القائمة البيضاء. ذو صلة بواجهات برمجة تطبيقات رابط إجراء البريد الإلكتروني.
لم يتم العثور على المستخدم لم يتم العثور على سجلّ مستخدم للمعرّف المحدّد.

Firebase Cloud Messaging

3_party_AUTH_ERROR شهادة أسماء نقاط الوصول (APN) أو مفتاح واجهة برمجة التطبيقات للمصادقة على الويب غير صالح أو غير متوفّر.
قيمة غير صالحة واحدة أو أكثر من الوسيطات المحددة في الطلب كانت غير صالحة.
للاستخدام الداخلي حدث خطأ في الخادم الداخلي.
الحصة الإجمالية تم تجاوز حد الإرسال لهدف الرسالة.
عدد المشتركين يختلف رقم تعريف المُرسِل الذي تمت مصادقته عن معرّف المُرسِل للرمز المميز للتسجيل. يعني هذا عادةً أن المُرسِل والرمز المميز للتسجيل المستهدف ليسا في مشروع Firebase نفسه.
معلومات غير متوفرة خدمة Cloud Messaging غير متاحة مؤقتًا.
غير مُسجَّل تم إلغاء تسجيل مثيل التطبيق من خدمة "المراسلة عبر السحابة الإلكترونية من Firebase". يعني هذا عادةً أنّ الرمز المميّز لتسجيل الجهاز المُستخدَم لم يعد صالحًا ويجب استخدام رمز جديد.

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

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

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

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

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

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

لا تتوافق "حزمة SDK للمشرف" في Python حاليًا مع عنوان Retry-After. ولا تدعم سوى الرقود الأسي البسيط.

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

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

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

جافا

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

Python

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)

.Net

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());
  }
}

Python

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)

.Net

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());
  }
}

Python

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
}

.Net

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 التي تم إرجاعها بواسطة خدمة خلفية وتنفيذ بعض الإجراءات أثناء التعامل مع الأخطاء. 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());
  }
}

Python

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
}

.Net

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