Xử lý lỗi SDK dành cho quản trị viên

Lỗi SDK dành cho quản trị viên được chia thành 2 loại:

  1. Lỗi lập trình: Đây là các lỗi lập trình và cấu hình trong ứng dụng của người dùng. Chúng chủ yếu xảy ra do sử dụng SDK không đúng cách (chẳng hạn như truyền null đến một phương thức không chấp nhận giá trị null), và các lỗi cấu hình khác ở cấp SDK hoặc dự án Firebase (bị thiếu thông tin xác thực, chuỗi mã dự án không chính xác, v.v.).
  2. Lỗi API: Đây bao gồm nhiều lỗi có thể khôi phục xảy ra trong quá trình triển khai SDK, tất cả các lỗi bắt nguồn từ các dịch vụ phụ trợ của Firebase và các lỗi tạm thời các lỗi (chẳng hạn như hết thời gian chờ) có thể xảy ra khi thực hiện lệnh gọi RPC.

SDK dành cho quản trị viên báo hiệu về lỗi lập trình bằng cách đưa ra một lỗi có nguồn gốc từ nền tảng được đề cập.

  • Java: Gửi các thực thể của IllegalArgumentException, NullPointerException hoặc loại lỗi thời gian chạy tích hợp sẵn tương tự.
  • Python: Tăng các thực thể của ValueError, TypeError hoặc loại lỗi tích hợp sẵn khác.
  • Go: Trả về lỗi chung.
  • .NET: Gửi các thực thể của ArgumentException, ArgumentNullException hoặc loại lỗi tích hợp sẵn tương tự.

Trong hầu hết các trường hợp, bạn không nên xử lý rõ ràng các lỗi lập trình. Thay vào đó, bạn nên sửa mã và cấu hình để tránh hoàn toàn các lỗi lập trình. Hãy xem xét đoạn mã Java sau:

String uid = getUserInput();

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

Nếu phương thức getUserInput() trả về null hoặc chuỗi trống, API FirebaseAuth.getUser() gửi một IllegalArgumentException. Thay vì xử lý rõ ràng vấn đề, bạn có thể giảm thiểu vấn đề bằng cách đảm bảo Phương thức getUserInput() không bao giờ trả về chuỗi UID không hợp lệ. Nếu không phải có thể, hãy triển khai việc kiểm tra đối số cần thiết trong mã của riêng bạn như sau:

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

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

Theo nguyên tắc, đừng bao giờ thử lại khi gặp lỗi lập trình. Cho phép dự phòng nhanh ngữ nghĩa về lỗi lập trình thường là hướng hành động tốt nhất vì nó tiết lộ lỗi lập trình và lỗi cấu hình trong quá trình phát triển, nơi chúng đều có thể kịp thời được khắc phục. Việc chạy lỗi nhanh trong trường hợp này có thể đồng nghĩa với việc cho phép lỗi truyền đến trình xử lý lỗi chung trong ứng dụng của bạn hoặc chỉ ghi nhật ký chúng cho mục đích kiểm tra, sau đó là việc chấm dứt luồng thực thi hiện tại (ứng dụng sẽ không gặp sự cố). Nói chung, hãy theo dõi lỗi xử lý các phương pháp hay nhất về ngôn ngữ lập trình của bạn và ứng dụng khung. Chỉ số này thường là đủ để giải quyết chính xác loại .

Thông thường, phần lớn nỗ lực xử lý lỗi của bạn sẽ tập trung vào xử lý API "lỗi.. Một số lỗi trong số này có thể khôi phục được, chẳng hạn như lỗi phát sinh từ dịch vụ tạm thời không hoạt động và một số dịch vụ thậm chí được dự kiến trong quy trình thực thi chương trình thông thường, chẳng hạn như phát hiện mã thông báo mã nhận dạng không hợp lệ hoặc đã hết hạn. Phần còn lại của hướng dẫn này trình bày cách SDK dành cho quản trị viên thể hiện các lỗi API như vậy, cũng như các lựa chọn xử lý chúng.

Cấu trúc của lỗi API

Một lỗi API có thể bao gồm các thành phần sau đây:

  1. Mã lỗi
  2. Thông báo lỗi
  3. Mã lỗi dịch vụ (Không bắt buộc)
  4. Phản hồi HTTP (Không bắt buộc)

Chúng tôi đảm bảo rằng mỗi lỗi API đều chứa một mã lỗi và một thông báo lỗi. Một số lỗi API nhất định cũng chứa mã lỗi dịch vụ dành riêng cho API đã tạo ra lỗi. Ví dụ: một số lỗi do tính năng Xác thực Firebase tạo ra API chứa mã lỗi dịch vụ dành riêng cho tính năng Xác thực Firebase. Nếu lỗi là kết quả của phản hồi lỗi HTTP từ dịch vụ phụ trợ, lỗi API cũng chứa phản hồi HTTP tương ứng. Bạn có thể dùng công cụ này để kiểm tra tiêu đề và nội dung chính xác của phản hồi gốc, điều này rất hữu ích cho gỡ lỗi, ghi nhật ký hoặc triển khai logic xử lý lỗi tinh vi hơn.

Tất cả phương thức triển khai SDK dành cho quản trị viên, ngoại trừ Node.js đều cung cấp các API cho phép truy cập các thành phần nêu trên của lỗi API.

Loại lỗi và API theo ngôn ngữ

Java

Trong Java, tất cả các lỗi API đều mở rộng lớp FirebaseException. Bạn có thể truy cập vào mã lỗi, thông báo lỗi và phản hồi HTTP không bắt buộc từ lớp cơ sở này.

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

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

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

Các API hiển thị mã lỗi dịch vụ sẽ cung cấp các lớp con dành riêng cho API của FirebaseException. Ví dụ: tất cả phương thức công khai trong API FirebaseAuth được khai báo để gửi các thực thể FirebaseAuthException. Bạn có thể truy cập vào mã lỗi dịch vụ từ lớp dẫn xuất này.

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

Python

Trong Python, tất cả các lỗi API đều mở rộng exceptions.FirebaseError . Bạn có thể truy cập vào mã lỗi, thông báo lỗi và giao thức HTTP không bắt buộc phản hồi từ lớp cơ sở này.

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

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

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

Hơn nữa, SDK quản trị Python cung cấp các lớp phái sinh riêng biệt cho từng mã lỗi. Chúng tôi gọi chúng là các lớp lỗi nền tảng.

class InvalidArgumentError(FirebaseError):
    # ...

class NotFoundError(FirebaseError):
    # ...

Bạn có thể tìm FirebaseError trong mã của mình và kiểm tra code của mã đó, hoặc thực hiện kiểm tra isinstance() đối với lớp lỗi nền tảng. Hoặc bạn có thể viết để trực tiếp phát hiện các loại lỗi nền tảng cụ thể. Phương pháp thứ hai là có thể khiến mã xử lý lỗi dễ đọc hơn.

Các API hiển thị mã lỗi dịch vụ sẽ cung cấp các lớp con dành riêng cho API của nền tảng các lớp lỗi khác. Ví dụ: tất cả phương thức công khai trong mô-đun auth đều có thể gửi (throw) Các loại lỗi theo API cụ thể như auth.UserNotFoundErrorauth.ExpiredIdTokenError.

class UserNotFoundError(exceptions.NotFoundError):
    # …

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

Tiến hành

SDK dành cho quản trị viên Go cung cấp một gói errorutils chứa một loạt các hàm cho phép kiểm thử mã lỗi.

package errorutils

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

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

Thông báo lỗi chỉ là chuỗi do hàm Error() của một . Bạn có thể truy cập phản hồi HTTP không bắt buộc bằng cách gọi hàm Hàm errorutils.HTTPResponse() trả về *http.Response.

Bạn có thể an toàn chuyển nil hoặc mọi giá trị lỗi khác vào quy trình kiểm tra lỗi các hàm trong gói errorutils. Các hàm này trả về true nếu đối số đầu vào thực sự chứa mã lỗi được đề cập và trả về false cho mọi kết quả khác. Hàm HTTPResponse() có hành vi tương tự, ngoại trừ việc trả về nil thay vì false.

Các API hiển thị mã lỗi dịch vụ cung cấp tính năng kiểm tra lỗi theo API cụ thể trong các gói tương ứng. Ví dụ: gói auth cung cấp các hàm IsUserNotFound()IsExpiredIDTokenError().

.NET

Trong .NET, tất cả các lỗi API đều mở rộng FirebaseException . Bạn có thể truy cập vào mã lỗi nền tảng, thông báo lỗi và phản hồi HTTP không bắt buộc từ cơ sở này .

public class FirebaseException : Exception {

    public ErrorCode ErrorCode { get; }

    public String Message { get; }

    public HttpResponseMessage HttpResponse { get; }
}

Các API hiển thị mã lỗi dịch vụ sẽ cung cấp các lớp con dành riêng cho API của FirebaseException. Ví dụ: mọi phương thức công khai trong API FirebaseAuth được khai báo để gửi các thực thể của FirebaseAuthException. Bạn có thể truy cập vào mã lỗi dịch vụ từ lớp dẫn xuất này.

public class FirebaseAuthException : FirebaseException {

    public AuthErrorCode AuthErrorCode { get; }
}

Mã lỗi nền tảng

Mã lỗi thường gặp trên tất cả các dịch vụ của Firebase và Google Cloud Platform. Bảng sau đây trình bày tất cả mã lỗi nền tảng có thể xảy ra. Đây là một danh sách ổn định và dự kiến sẽ không thay đổi trong một thời gian dài.

Hàm INVALID_ARGUMENT Ứng dụng khách chỉ định đối số không hợp lệ
FAILED_PRECONDITION Không thể thực thi yêu cầu ở trạng thái hệ thống hiện tại, chẳng hạn như xoá một thư mục không trống.
NGOÀI_ PHẠM VI Ứng dụng khách chỉ định phạm vi không hợp lệ.
KHÔNG XÁC THỰC Yêu cầu chưa được xác thực do mã thông báo OAuth bị thiếu, không hợp lệ hoặc đã hết hạn.
PERMISSION_DENIED Ứng dụng khách không có đủ quyền. Điều này có thể xảy ra do mã thông báo OAuth không có phạm vi phù hợp, ứng dụng không có quyền hoặc API chưa được bật cho dự án ứng dụng.
NOT_FOUND Không tìm thấy tài nguyên đã chỉ định hoặc yêu cầu bị từ chối vì những lý do không được tiết lộ, chẳng hạn như danh sách cho phép.
XUNG ĐỘT Xung đột tình trạng đồng thời, ví dụ như xung đột read-modify-write. Chỉ một số dịch vụ cũ sử dụng. Hầu hết các dịch vụ đều sử dụng ABORTED hoặc ALREADY_EXISTS để thay thế cho loại này. Hãy tham khảo tài liệu dành riêng cho từng dịch vụ để xem cần xử lý vấn đề nào trong mã của bạn.
ĐÃ THANH TOÁN Xung đột tình trạng đồng thời, ví dụ như xung đột read-modify-write.
ĐÃ_CÓ_SỚM Tài nguyên mà ứng dụng khách tìm cách tạo đã tồn tại.
RESOURCE_EXHAUSTED Hết định mức tài nguyên hoặc đã đạt đến tốc độ giới hạn.
ĐÃ HỦY Ứng dụng khách đã hủy yêu cầu.
MẤT_DỮ LIỆU Mất hoặc hư hỏng dữ liệu và không phục hồi được. Khách hàng phải báo cáo lỗi cho người dùng.
KHÔNG XÁC ĐỊNH Lỗi máy chủ không xác định. Thường là lỗi máy chủ.

Mã lỗi này cũng được gán cho các lỗi phân tích cú pháp phản hồi cục bộ (unmarshal) và một loạt các lỗi I/O cấp thấp khác không dễ dàng chẩn đoán được.

NỘI BỘ Lỗi máy chủ nội bộ. Thường là lỗi máy chủ.
KHÔNG CÓ Không có dịch vụ. Thông thường, máy chủ tạm thời không hoạt động.

Mã lỗi này cũng được gán cho các lỗi mạng cục bộ (kết nối bị từ chối, không có đường dẫn đến máy chủ).

DEADLINE_EXCEEDED Đã quá hạn chót cho yêu cầu. Điều này sẽ chỉ xảy ra nếu phương thức gọi đặt thời hạn ngắn hơn thời hạn mặc định của API mục tiêu (tức là thời hạn được yêu cầu không đủ để máy chủ xử lý yêu cầu) và yêu cầu không kết thúc trong thời hạn đó.

Mã lỗi này cũng được gán cho kết nối cục bộ và thời gian chờ đọc.

Hầu hết API chỉ có thể gây ra một số mã lỗi nêu trên. Trong mọi trường hợp, bạn không được dự kiến sẽ xử lý rõ ràng tất cả các mã lỗi này khi triển khai trình xử lý lỗi. Hầu hết các ứng dụng sẽ chỉ quan tâm đến 1 đến 2 mã lỗi cụ thể và xem mọi lỗi khác là lỗi chung và không thể khôi phục lỗi.

Mã lỗi dành riêng cho từng dịch vụ

Firebase Auth

CHỨNG CHỈ TÌM THẤY RẤT ĐÚNG Không tìm nạp được chứng chỉ khoá công khai cần thiết để xác minh JWT (mã thông báo giá trị nhận dạng hoặc cookie của phiên).
EMAIL_ALREADY_EXISTS Đã có một người dùng với email được cung cấp.
EXPIRED_ID_TOKEN Mã thông báo mã nhận dạng được chỉ định cho verifyIdToken() đã hết hạn.
EXPIRED_SESSION_COOKIE Cookie phiên được chỉ định cho verifySessionCookie() iis đã hết hạn.
KHÔNG_ động_LINK_DOMAIN Miền đường liên kết động đã cung cấp chưa được định cấu hình hoặc chưa được uỷ quyền đối với dự án hiện tại. Liên quan đến API đường liên kết để thao tác qua email.
INVALID_ID_TOKEN Mã thông báo nhận dạng được chỉ định cho verifyIdToken() là không hợp lệ.
INVALID_SESSION_COOKIE Cookie phiên được chỉ định cho verifySessionCookie() là không hợp lệ.
PHONE_NUMBER_ALREADY_EXISTS Người dùng đã tồn tại với số điện thoại được cung cấp.
REVOKED_ID_TOKEN Mã thông báo nhận dạng được chỉ định cho verifyIdToken() sẽ bị thu hồi.
REVOKED_SESSION_COOKIE Cookie phiên được chỉ định cho verifySessionCookie() đã hết hạn.
KHÔNG ỦY_ QUYỀN_CONTINUE_URL Miền của URL tiếp tục không có trong danh sách cho phép. Liên quan đến API đường liên kết để thao tác qua email.
NGƯỜI DÙNG_KHÔNG_TÌM THẤY Không tìm thấy bản ghi người dùng cho giá trị nhận dạng đã cho.

Firebase Cloud Messaging

THỨ BA BÊN_XÁC THỰC_ERROR Thiếu khoá API xác thực thông báo đẩy trên web hoặc chứng chỉ APN hoặc khoá API xác thực thông báo đẩy trên web không hợp lệ hoặc bị thiếu.
Hàm INVALID_ARGUMENT Một hoặc nhiều đối số được chỉ định trong yêu cầu không hợp lệ.
NỘI BỘ Lỗi máy chủ nội bộ.
Hàm QUOTA_EXCEEDED Đã vượt quá giới hạn gửi đối với mục tiêu thư.
SENDER_ID_MISMATCH Mã nhận dạng người gửi đã xác thực khác với mã nhận dạng người gửi của mã thông báo đăng ký. Điều này thường có nghĩa là người gửi và mã thông báo đăng ký đích không ở trong cùng một dự án Firebase.
KHÔNG CÓ Dịch vụ Cloud Messaging tạm thời không hoạt động.
CHƯA ĐĂNG KÝ Phiên bản ứng dụng đã bị huỷ đăng ký khỏi FCM. Điều này thường có nghĩa là mã thông báo đăng ký thiết bị được sử dụng không còn hợp lệ và bạn phải sử dụng mã mới.

Thử lại tự động

SDK dành cho quản trị viên tự động thử lại một số lỗi trước khi hiển thị các lỗi đó cho người dùng. Nói chung, các loại lỗi sau đây được thử lại một cách rõ ràng:

  • Tất cả lỗi API do phản hồi HTTP 503 (Dịch vụ không có sẵn).
  • Một số lỗi API do phản hồi HTTP 500 (Lỗi máy chủ nội bộ).
  • Hầu hết các lỗi I/O cấp thấp (kết nối bị từ chối, kết nối đặt lại, v.v.).

SDK sẽ thử lại tối đa 5 lần từng lỗi nêu trên (lần thử ban đầu) + 4 lần thử lại) có thời gian đợi luỹ thừa. Bạn có thể triển khai hoạt động thử lại của riêng mình các cơ chế ở cấp ứng dụng nếu muốn, nhưng đây thường không phải là là bắt buộc.

Thử lại sau khi hỗ trợ

Việc triển khai Go và .NET của SDK dành cho quản trị viên đi kèm với khả năng hỗ trợ cho xử lý tiêu đề HTTP Retry-After. Tức là, nếu phản hồi lỗi được gửi bởi máy chủ phụ trợ chứa tiêu đề Retry-After chuẩn, SDK sẽ khi thử lại, miễn là thời gian chờ được chỉ định không phải lâu hơn. Nếu tiêu đề Retry-After cho biết thời gian chờ rất dài thì SDK sẽ bỏ qua các lần thử lại và báo lỗi API thích hợp.

SDK quản trị Python hiện không hỗ trợ tiêu đề Retry-After và chỉ hỗ trợ thuật toán thời gian đợi luỹ thừa đơn giản.

Ví dụ về cách xử lý lỗi API

Triển khai trình xử lý lỗi chung

Trong hầu hết các trường hợp, điều bạn muốn là một trình xử lý lỗi chung giúp thu thập để ngăn chặn việc chấm dứt luồng chương trình ngoài dự kiến do có Lỗi API. Những trình xử lý lỗi như vậy thường chỉ ghi lại lỗi cho mục đích kiểm tra, hoặc gọi một số quy trình xử lý lỗi mặc định khác cho tất cả API gặp phải . Họ không hẳn là quan tâm đến các mã lỗi khác nhau hoặc lý do nào khác có thể gây ra lỗi này.

Java

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}')

Tiến hành

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

Đang kiểm tra mã lỗi

Trong một số trường hợp, bạn nên kiểm tra mã lỗi chính xác và gọi các quy trình xử lý lỗi nhận biết theo bối cảnh khác nhau. Trong ví dụ sau, chúng tôi có một trình xử lý lỗi ghi lại các thông báo lỗi cụ thể hơn dựa trên mã lỗi dịch vụ.

Java

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}')

Tiến hành

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

Sau đây là một ví dụ khác mà chúng tôi kiểm tra cả mã lỗi cấp cao nhất và mã lỗi dịch vụ:

Java

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}')

Tiến hành

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

Truy cập vào phản hồi HTTP

Trong một số ít trường hợp, bạn có thể muốn kiểm tra phản hồi lỗi HTTP được trả về bởi một dịch vụ phụ trợ và thực hiện thao tác xử lý lỗi nào đó trên dịch vụ đó. SDK dành cho quản trị viên hiển thị cả tiêu đề và nội dung của các phản hồi lỗi này. Phản hồi nội dung thường được trả về dưới dạng một chuỗi hoặc một chuỗi byte thô và có thể được phân tích cú pháp thành mọi định dạng mục tiêu cần thiết.

Java

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}')

Tiến hành

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