خطاهای Admin SDK به دو دسته تقسیم می شوند:
- خطاهای برنامه نویسی: این خطاهای برنامه نویسی و پیکربندی در برنامه کاربر است. آنها بیشتر به دلیل استفاده نادرست از SDK (مانند ارسال
null
به روشی که مقادیرnull
نمی پذیرد) و سایر خطاهای پیکربندی در سطح پروژه Firebase یا SDK (عدم اعتبار، رشته ID پروژه نادرست و غیره رخ می دهد). بر). - خطاهای API: این خطاها شامل خطاهای مختلف قابل بازیابی است که در پیادهسازی SDK رخ میدهد، همه خطاهایی که در سرویسهای پشتیبان Firebase منشأ میگیرند، و سایر خطاهای گذرا (مانند زمانبندی) که ممکن است هنگام برقراری تماسهای RPC رخ دهند.
Admin SDK با پرتاب خطای بومی پلتفرم مورد نظر، خطاهای برنامه نویسی را نشان می دهد.
- جاوا: نمونه هایی از
IllegalArgumentException
،NullPointerException
یا نوع خطای داخلی مشابه را پرتاب می کند. - Python: نمونه هایی از
ValueError
،TypeError
یا دیگر نوع خطاهای داخلی را افزایش می دهد. - Go: یک خطای عمومی را برمیگرداند.
- .NET: نمونه هایی از
ArgumentException
،ArgumentNullException
یا نوع خطای داخلی مشابه را پرتاب می کند.
در بیشتر مواقع نباید به طور صریح با خطاهای برنامه نویسی برخورد کنید. در عوض، باید کد و پیکربندی خود را اصلاح کنید تا از خطاهای برنامه نویسی به طور کلی جلوگیری کنید. قطعه جاوا زیر را در نظر بگیرید:
String uid = getUserInput();
UserRecord user = FirebaseAuth.getInstance().getUser(uid);
اگر متد getUserInput()
رشتههای null
یا تهی را برگرداند، API 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);
به عنوان یک اصل، هرگز اشتباهات برنامه نویسی را تکرار نکنید. اجازه دادن به معنیشناسی سریع خطا در خطاهای برنامهنویسی اغلب بهترین اقدام است، زیرا باگهای برنامهنویسی و خطاهای پیکربندی را در طول توسعه آشکار میکند، جایی که میتوان آنها را به سرعت برطرف کرد. Fail-fast در این زمینه می تواند به این معنی باشد که اجازه دهید خطاها به یک کنترل کننده خطای جهانی در برنامه شما منتشر شوند، یا فقط آنها را برای اهداف ممیزی ثبت کنید و سپس جریان اجرای فعلی را خاتمه دهید (برنامه نباید از کار بیفتد). به طور کلی، خطاهای مدیریت بهترین روش های زبان برنامه نویسی و چارچوب برنامه را دنبال کنید. این به تنهایی اغلب برای برخورد صحیح با این دسته از خطاها کافی است.
به طور معمول، عمده تلاشهای شما برای رسیدگی به خطاها بر مدیریت خطاهای API متمرکز میشود. برخی از این خطاها قابل بازیابی هستند، مانند خطاهایی که ناشی از یک سرویس موقتاً در دسترس نیست، و برخی حتی در جریان اجرای عادی برنامه پیشبینی میشوند، مانند تشخیص شناسههای نامعتبر یا منقضی شده. بقیه این راهنما نشان میدهد که Admin SDK چگونه خطاهای API را نشان میدهد و گزینههای مختلفی که برای رسیدگی به آنها در دسترس است.
ساختار یک خطای API
یک خطای API از اجزای زیر تشکیل شده است:
- کد خطا
- پیغام خطا
- کد خطای سرویس (اختیاری)
- پاسخ HTTP (اختیاری)
هر خطای API دارای یک کد خطا و یک پیام خطا تضمین می شود. برخی از خطاهای API همچنین حاوی یک کد خطای سرویس هستند که مختص API است که این خطا را ایجاد کرده است. به عنوان مثال برخی از خطاهای ایجاد شده توسط Firebase Auth API حاوی کد خطای سرویس است که مخصوص Firebase Auth است. اگر خطا نتیجه یک پاسخ خطای HTTP از یک سرویس پشتیبان باشد، خطای API حاوی پاسخ HTTP مربوطه نیز می باشد. این می تواند برای بررسی سرصفحه ها و محتویات پاسخ اصلی استفاده شود، که برای اشکال زدایی، ورود به سیستم یا اجرای منطق مدیریت خطای پیچیده تر مفید است.
همه پیادهسازیهای Admin SDK به جز Node.js APIهایی را ارائه میکنند که دسترسی به اجزای بالا از خطاهای API را امکانپذیر میسازد.
انواع خطا و API بر اساس زبان
جاوا
در جاوا تمام خطاهای API کلاس FirebaseException
را گسترش می دهند. می توانید به کد خطا، پیام خطا و پاسخ HTTP اختیاری از این کلاس پایه دسترسی داشته باشید.
public class FirebaseException extends Exception {
@NonNull
public ErrorCode getErrorCode() {
// ...
}
@NonNull
public String getMessage() {
// ...
}
@Nullable
public IncomingHttpResponse getHttpResponse() {
// ...
}
}
APIهایی که کدهای خطای سرویس را در معرض نمایش میگذارند، زیرکلاسهای مخصوص 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()
در برابر کلاس خطای پلتفرم انجام دهید. یا می توانید کدی بنویسید تا مستقیماً انواع خطاهای پلتفرم خاصی را دریافت کنید. رویکرد دوم احتمالاً منجر به کدهای مدیریت خطای خواناتر می شود.
APIهایی که کدهای خطای سرویس را نشان میدهند، زیر کلاسهای API خاص از کلاسهای خطای پلتفرم را ارائه میکنند. به عنوان مثال، همه روشهای عمومی در ماژول 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 true
برمیگردانند و برای هر چیز دیگری false
برمیگردانند. تابع HTTPResponse()
رفتاری مشابه دارد، با این تفاوت که به جای false
nil
برمی گرداند.
APIهایی که کدهای خطای سرویس را نشان میدهند، عملکردهای بررسی خطای خاص API را در بستههای مربوطه ارائه میکنند. به عنوان مثال، بسته auth
توابع IsUserNotFound()
و IsExpiredIDTokenError()
را ارائه می کند.
.خالص
در NET همه خطاهای API کلاس FirebaseException
را گسترش می دهند. می توانید به کد خطای پلتفرم، پیام خطا و پاسخ اختیاری HTTP از این کلاس پایه دسترسی داشته باشید.
public class FirebaseException : Exception {
public ErrorCode ErrorCode { get; }
public String Message { get; }
public HttpResponseMessage HttpResponse { get; }
}
APIهایی که کدهای خطای سرویس را در معرض نمایش میگذارند، زیرکلاسهای مخصوص API از FirebaseException
را ارائه میکنند. برای مثال، همه روشهای عمومی در FirebaseAuth
API برای پرتاب نمونههایی از FirebaseAuthException
اعلام شدهاند. از این کلاس مشتق شده می توانید به کد خطای سرویس دسترسی پیدا کنید.
public class FirebaseAuthException : FirebaseException {
public AuthErrorCode AuthErrorCode { get; }
}
کدهای خطای پلتفرم
کدهای خطا در همه سرویسهای Firebase و Google Cloud Platform رایج هستند. جدول زیر تمام کدهای خطای احتمالی پلتفرم را نشان می دهد. این یک لیست ثابت است و انتظار می رود برای مدت طولانی بدون تغییر باقی بماند.
INVALID_ARGUMENT | کلاینت آرگومان نامعتبری را مشخص کرده است. |
FAILED_PRECONDITION | درخواست را نمی توان در وضعیت فعلی سیستم اجرا کرد، مانند حذف دایرکتوری غیر خالی. |
OUT_OF_RANGE | کلاینت محدوده نامعتبری را مشخص کرده است. |
بدون احراز هویت | درخواست به دلیل گم شدن، نامعتبر یا منقضی شده OAuth تأیید اعتبار نشد. |
PERMISSION_DENIED | مشتری مجوز کافی ندارد. این ممکن است به این دلیل اتفاق بیفتد که توکن OAuth محدوده مناسبی ندارد، مشتری مجوز ندارد یا API برای پروژه مشتری فعال نشده است. |
پیدا نشد | منبع مشخصی یافت نشد، یا درخواست به دلایل نامعلومی مانند قرار گرفتن در لیست سفید رد شد. |
تعارض | تضاد همزمانی، مانند تضاد خواندن، اصلاح و نوشتن. فقط توسط چند سرویس قدیمی استفاده می شود. اکثر سرویس ها به جای این مورد از ABORTED یا ALREADY_EXISTS استفاده می کنند. برای اینکه ببینید کدام یک را در کد خود باید مدیریت کنید، به اسناد خاص سرویس مراجعه کنید. |
سقط شد | تضاد همزمانی، مانند تضاد خواندن، اصلاح و نوشتن. |
درحال حاضر وجود دارد | منبعی که یک مشتری سعی کرد ایجاد کند، از قبل وجود دارد. |
RESOURCE_EXHAUSTED | یا خارج از سهمیه منابع یا رسیدن به محدودیت نرخ. |
لغو شد | درخواست توسط مشتری لغو شد. |
از دست رفتن داده ها | از دست دادن اطلاعات غیرقابل جبران یا خرابی داده ها. مشتری باید خطا را به کاربر گزارش کند. |
ناشناخته | خطای سرور ناشناخته به طور معمول یک باگ سرور. این کد خطا همچنین به خطاهای تجزیه پاسخ محلی (unmarshal) و طیف گسترده ای از دیگر خطاهای سطح پایین ورودی/خروجی که به راحتی قابل تشخیص نیستند اختصاص داده می شود. |
درونی؛ داخلی | خطای سرور داخلی به طور معمول یک باگ سرور. |
غیر قابل دسترسی | سرویس در دسترس نیست. معمولاً سرور موقتاً از کار افتاده است. این کد خطا به خطاهای شبکه محلی نیز اختصاص داده می شود (اتصال رد شد، مسیری برای میزبانی وجود ندارد). |
DEADLINE_EXCEEDED | مهلت درخواست فراتر رفت. این تنها در صورتی اتفاق میافتد که تماسگیرنده ضربالاجلی کوتاهتر از مهلت پیشفرض API هدف تعیین کند (یعنی مهلت درخواستی برای پردازش درخواست توسط سرور کافی نباشد)، و درخواست در مهلت تعیین شده به پایان نرسد. این کد خطا به زمان های اتصال محلی و خواندن نیز اختصاص داده می شود. |
اکثر APIها فقط می توانند به زیر مجموعه ای از کدهای خطای بالا منجر شوند. در هر صورت، از شما انتظار نمی رود که به طور صریح تمام این کدهای خطا را هنگام پیاده سازی کنترل کننده های خطا مدیریت کنید. اکثر برنامه ها فقط به 1-2 کد خطای خاص علاقه مند هستند و بقیه موارد را به عنوان یک شکست عمومی و غیرقابل جبران در نظر می گیرند.
کدهای خطای خاص سرویس
Firebase Auth
CERTIFICATE_FETCH_FAILED | واکشی گواهینامه های کلید عمومی مورد نیاز برای تأیید JWT (نشانه شناسه یا کوکی جلسه) انجام نشد. |
EMAIL_ALREADY_EXISTS | یک کاربر از قبل با ایمیل ارائه شده وجود دارد. |
EXPIRED_ID_TOKEN | کد شناسه مشخص شده برای verifyIdToken() منقضی شده است. |
EXPIRED_SESSION_COOKIE | کوکی جلسه مشخص شده برای verifySessionCookie() منقضی شده است. |
INVALID_DYNAMIC_LINK_DOMAIN | دامنه پیوند پویا ارائه شده برای پروژه فعلی پیکربندی یا مجاز نیست. مربوط به APIهای پیوند اقدام ایمیل. |
INVALID_ID_TOKEN | کد شناسه مشخص شده برای verifyIdToken() نامعتبر است. |
INVALID_SESSION_COOKIE | کوکی جلسه مشخص شده برای verifySessionCookie() نامعتبر است. |
PHONE_NUMBER_ALREADY_EXISTS | یک کاربر از قبل با شماره تلفن ارائه شده وجود دارد. |
REVOKED_ID_TOKEN | کد شناسه مشخص شده برای verifyIdToken() باطل می شود. |
REVOKED_SESSION_COOKIE | کوکی جلسه مشخص شده برای verifySessionCookie() منقضی شده است. |
UNAUTHORIZED_CONTINUE_URL | دامنه ادامه URL در لیست سفید نیست. مربوط به APIهای پیوند اقدام ایمیل. |
USER_NOT_FOUND | هیچ سابقه کاربری برای شناسه داده شده یافت نشد. |
Firebase Cloud Messaging
THIRD_PARTY_AUTH_ERROR | گواهینامه APN یا کلید API auth web push نامعتبر یا گم شده بود. |
INVALID_ARGUMENT | یک یا چند آرگومان مشخص شده در درخواست نامعتبر بود. |
درونی؛ داخلی | خطای سرور داخلی |
QUOTA_EXCEEDED | از محدودیت ارسال برای هدف پیام فراتر رفته است. |
SENDER_ID_MISMATCH | شناسه فرستنده احراز هویت شده با شناسه فرستنده رمز ثبت نام متفاوت است. این معمولاً به این معنی است که فرستنده و نشانه ثبت نام هدف در پروژه Firebase یکسان نیستند. |
غیر قابل دسترسی | سرویس Cloud Messaging موقتاً در دسترس نیست. |
ثبت نشده | نمونه برنامه از FCM لغو ثبت شد. این معمولاً به این معنی است که رمز ثبت دستگاه استفاده شده دیگر معتبر نیست و باید از یک رمز جدید استفاده شود. |
تلاش مجدد خودکار
Admin SDK به طور خودکار خطاهای خاصی را قبل از افشای آن خطاها به کاربران تکرار می کند. به طور کلی، انواع خطاهای زیر به طور شفاف دوباره امتحان می شوند:
- همه خطاهای API ناشی از پاسخهای HTTP 503 (سرویس در دسترس نیست).
- برخی از خطاهای API ناشی از پاسخهای HTTP 500 (خطای سرور داخلی).
- اکثر خطاهای سطح پایین I/O (اتصال رد شد، اتصال مجدد تنظیم شد و غیره).
SDK هر یک از خطاهای بالا را حداکثر تا 5 بار (تلاش اصلی + 4 تلاش مجدد) با عقب نشینی نمایی تکرار می کند. اگر بخواهید میتوانید مکانیسمهای امتحان مجدد خود را در سطح برنامه پیادهسازی کنید، اما این معمولاً لازم نیست.
تلاش مجدد - بعد از پشتیبانی
پیادهسازی Go و .NET Admin SDK با پشتیبانی از هدر HTTP Retry-After
ارائه میشود. به این معنا که اگر پاسخ خطای ارسال شده توسط سرورهای باطن حاوی سرآیند Retry-After
استاندارد باشد، SDK در هنگام تلاش مجدد تا زمانی که مدت انتظار مشخص شده خیلی طولانی نباشد، به آن احترام می گذارد. اگر سرصفحه Retry-After
مدت زمان انتظار بسیار طولانی را نشان دهد، SDK از تلاش های مجدد عبور می کند و خطای API مناسب را ایجاد می کند.
Python Admin SDK در حال حاضر از هدر Retry-After
پشتیبانی نمی کند و فقط از backoff ساده نمایی پشتیبانی می کند.
نمونه های مدیریت خطای API
پیاده سازی یک کنترل کننده خطای عمومی
در بیشتر موارد آنچه شما می خواهید یک کنترل کننده خطای عمومی است که طیف وسیعی از خطاها را برای جلوگیری از خاتمه غیرمنتظره جریان برنامه به دلیل یک خطای 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}");
}
}