Admin-SDK-Fehler sind in zwei Kategorien unterteilt:
- Programmierfehler: Hierbei handelt es sich um Programmier- und Konfigurationsfehler in der Benutzeranwendung. Sie treten meist aufgrund der falschen Verwendung des SDK (z. B. Übergabe
null
an eine Methode, die keinenull
akzeptiert) und anderen Konfigurationsfehlern auf Firebase-Projekt- oder SDK-Ebene (fehlende Anmeldeinformationen, falsche Projekt-ID-Zeichenfolge usw.) auf An). - API-Fehler: Dazu gehören verschiedene behebbare Fehler, die innerhalb der SDK-Implementierung auftreten, alle Fehler, die von Firebase-Backend-Diensten ausgehen, und andere vorübergehende Fehler (z. B. Zeitüberschreitungen), die bei RPC-Aufrufen auftreten können.
Das Admin SDK signalisiert Programmierfehler , indem es einen Fehler auslöst, der für die betreffende Plattform typisch ist.
- Java: Löst Instanzen von
IllegalArgumentException
,NullPointerException
oder einem ähnlichen integrierten Laufzeitfehlertyp aus. - Python: Löst Instanzen von
ValueError
,TypeError
oder einem anderen integrierten Fehlertyp aus. - Go: Gibt einen allgemeinen Fehler zurück.
- .NET: Löst Instanzen von
ArgumentException
,ArgumentNullException
oder einem ähnlichen integrierten Fehlertyp aus.
In den meisten Situationen sollten Sie Programmierfehler nicht explizit behandeln. Stattdessen sollten Sie Ihren Code und Ihre Konfiguration korrigieren, um Programmierfehler insgesamt zu vermeiden. Betrachten Sie den folgenden Java-Snippet:
String uid = getUserInput();
UserRecord user = FirebaseAuth.getInstance().getUser(uid);
Wenn die getUserInput()
-Methode null
oder leere Zeichenfolgen zurückgibt, löst die FirebaseAuth.getUser()
API eine IllegalArgumentException
aus. Anstatt es explizit zu behandeln, können Sie das Problem entschärfen, indem Sie sicherstellen, dass die getUserInput()
Methode niemals eine ungültige UID-Zeichenfolge zurückgibt. Wenn dies nicht möglich ist, implementieren Sie die erforderliche Argumentüberprüfung wie folgt in Ihrem eigenen Code:
String uid = getUserInput();
if (Strings.isNullOrEmpty(uid)) {
log.warn("UID must not be null or empty");
return;
}
UserRecord user = FirebaseAuth.getInstance().getUser(uid);
Versuchen Sie es grundsätzlich nie erneut bei Programmierfehlern. Die Berücksichtigung einer Fail-Fast-Semantik bei Programmierfehlern ist häufig die beste Vorgehensweise, da dadurch Programmierfehler und Konfigurationsfehler während der Entwicklung aufgedeckt werden, wo sie umgehend behoben werden können. Fail-Fast kann in diesem Zusammenhang bedeuten, dass die Fehler an einen globalen Fehlerhandler in Ihrer Anwendung weitergegeben werden oder sie einfach zu Prüfzwecken protokolliert werden, gefolgt von der Beendigung des aktuellen Ausführungsflusses (die Anwendung sollte nicht abstürzen müssen). Befolgen Sie im Allgemeinen die Best Practices für die Fehlerbehandlung Ihrer Programmiersprache und des Anwendungsframeworks. Dies allein reicht oft aus, um diese Fehlerklasse richtig zu behandeln.
Normalerweise konzentriert sich der Großteil Ihrer Fehlerbehandlungsbemühungen auf die Behandlung von API-Fehlern . Einige dieser Fehler sind behebbar, beispielsweise Fehler, die aus einem vorübergehend nicht verfügbaren Dienst resultieren, und einige werden sogar während des normalen Programmausführungsablaufs erwartet, beispielsweise beim Erkennen ungültiger oder abgelaufener ID-Token. Im Rest dieses Leitfadens wird beschrieben, wie das Admin SDK solche API-Fehler darstellt und welche verschiedenen Optionen zur Behandlung dieser Fehler verfügbar sind.
Struktur eines API-Fehlers
Ein API-Fehler besteht aus folgenden Komponenten:
- Fehlercode
- Fehlermeldung
- Dienstfehlercode (optional)
- HTTP-Antwort (optional)
Jeder API-Fehler enthält garantiert einen Fehlercode und eine Fehlermeldung. Bestimmte API-Fehler enthalten auch einen Dienstfehlercode, der spezifisch für die API ist, die den Fehler generiert hat. Beispielsweise enthalten einige von der Firebase Auth-API generierte Fehler einen Dienstfehlercode, der spezifisch für Firebase Auth ist. Wenn der Fehler das Ergebnis einer HTTP-Fehlerantwort eines Backend-Dienstes war, enthält der API-Fehler auch die entsprechende HTTP-Antwort. Dies kann verwendet werden, um die genauen Header und Inhalte der ursprünglichen Antwort zu überprüfen, was zum Debuggen, Protokollieren oder Implementieren einer ausgefeilteren Fehlerbehandlungslogik nützlich ist.
Alle Admin SDK-Implementierungen außer Node.js stellen APIs bereit, die den Zugriff auf die oben genannten Komponenten von API-Fehlern ermöglichen.
Fehlertypen und APIs nach Sprache
Java
In Java erweitern alle API-Fehler die FirebaseException
Klasse. Von dieser Basisklasse aus können Sie auf den Fehlercode, die Fehlermeldung und die optionale HTTP-Antwort zugreifen.
public class FirebaseException extends Exception {
@NonNull
public ErrorCode getErrorCode() {
// ...
}
@NonNull
public String getMessage() {
// ...
}
@Nullable
public IncomingHttpResponse getHttpResponse() {
// ...
}
}
APIs, die Dienstfehlercodes offenlegen, stellen API-spezifische Unterklassen von FirebaseException
bereit. Beispielsweise sind alle öffentlichen Methoden in der FirebaseAuth
API so deklariert, dass sie Instanzen von FirebaseAuthException
auslösen. Sie können über diese abgeleitete Klasse auf den Dienstfehlercode zugreifen.
public class FirebaseAuthException extends FirebaseException {
@Nullable
public AuthErrorCode getAuthErrorCode() {
// ...
}
}
Python
In Python erweitern alle API-Fehler die Klasse exceptions.FirebaseError
. Von dieser Basisklasse aus können Sie auf den Fehlercode, die Fehlermeldung und die optionale HTTP-Antwort zugreifen.
class FirebaseError(Exception):
@property
def code(self):
# ...
@property
def message(self):
# ...
@property
def http_response(self):
# ...
Darüber hinaus bietet das Python Admin SDK für jeden Fehlercode separate abgeleitete Klassen. Wir bezeichnen sie als Plattformfehlerklassen .
class InvalidArgumentError(FirebaseError):
# ...
class NotFoundError(FirebaseError):
# ...
Sie können entweder FirebaseError
in Ihrem Code abfangen und seinen code
überprüfen oder eine isinstance()
Prüfung anhand einer Plattformfehlerklasse durchführen. Oder Sie können Code schreiben, um bestimmte Plattformfehlertypen direkt abzufangen. Der letztere Ansatz führt wahrscheinlich zu besser lesbarem Fehlerbehandlungscode.
APIs, die Dienstfehlercodes offenlegen, stellen API-spezifische Unterklassen von Plattformfehlerklassen bereit. Beispielsweise können alle öffentlichen Methoden im auth
Modul API-spezifische Fehlertypen wie auth.UserNotFoundError
und auth.ExpiredIdTokenError
auslösen.
class UserNotFoundError(exceptions.NotFoundError):
# …
class ExpiredIdTokenError(exceptions.InvalidArgumentError):
# ...
Gehen
Das Go Admin SDK stellt ein errorutils
Paket bereit, das eine Reihe von Funktionen enthält, die das Testen auf Fehlercodes ermöglichen.
package errorutils
func IsInvalidArgument(err error) bool {
// ...
}
func IsNotFound(err error) bool {
// ...
}
Die Fehlermeldung ist einfach die Zeichenfolge, die von der Error()
-Funktion eines Fehlers zurückgegeben wird. Auf die optionale HTTP-Antwort kann durch Aufrufen der Funktion errorutils.HTTPResponse()
zugegriffen werden, die ein *http.Response
zurückgibt.
Es ist sicher, nil
oder einen anderen Fehlerwert an die Fehlerprüffunktionen im Paket errorutils
zu übergeben. Sie geben true
zurück, wenn das Eingabeargument tatsächlich den betreffenden Fehlercode enthält, und geben für alles andere false
zurück. Die Funktion HTTPResponse()
verhält sich ähnlich, außer dass sie nil
anstelle von false
zurückgibt.
APIs, die Dienstfehlercodes offenlegen, stellen API-spezifische Fehlerprüffunktionen in den entsprechenden Paketen bereit. Das auth
Paket stellt beispielsweise die Funktionen IsUserNotFound()
und IsExpiredIDTokenError()
bereit.
.NETZ
In .NET erweitern alle API-Fehler die FirebaseException
Klasse. Von dieser Basisklasse aus können Sie auf den Plattformfehlercode, die Fehlermeldung und die optionale HTTP-Antwort zugreifen.
public class FirebaseException : Exception {
public ErrorCode ErrorCode { get; }
public String Message { get; }
public HttpResponseMessage HttpResponse { get; }
}
APIs, die Dienstfehlercodes offenlegen, stellen API-spezifische Unterklassen von FirebaseException
bereit. Beispielsweise sind alle öffentlichen Methoden in der FirebaseAuth
API so deklariert, dass sie Instanzen von FirebaseAuthException
auslösen. Sie können über diese abgeleitete Klasse auf den Dienstfehlercode zugreifen.
public class FirebaseAuthException : FirebaseException {
public AuthErrorCode AuthErrorCode { get; }
}
Plattformfehlercodes
Fehlercodes sind bei allen Firebase- und Google Cloud Platform-Diensten gleich. In der folgenden Tabelle sind alle möglichen Plattformfehlercodes aufgeführt. Dies ist eine stabile Liste und wird voraussichtlich über einen langen Zeitraum unverändert bleiben.
UNGÜLTIGES ARGUMENT | Der Client hat ein ungültiges Argument angegeben. |
FAILED_PRECONDITION | Die Anforderung kann im aktuellen Systemstatus nicht ausgeführt werden, z. B. beim Löschen eines nicht leeren Verzeichnisses. |
AUSSER REICHWEITE | Der Client hat einen ungültigen Bereich angegeben. |
UNAUTHENTIFIZIERT | Die Anfrage wurde aufgrund eines fehlenden, ungültigen oder abgelaufenen OAuth-Tokens nicht authentifiziert. |
ZUGRIFF VERWEIGERT | Der Kunde verfügt nicht über ausreichende Berechtigungen. Dies kann passieren, weil das OAuth-Token nicht über die richtigen Bereiche verfügt, der Client nicht über die entsprechende Berechtigung verfügt oder die API für das Clientprojekt nicht aktiviert wurde. |
NICHT GEFUNDEN | Die angegebene Ressource wurde nicht gefunden oder die Anfrage wurde aus unbekannten Gründen wie Whitelisting abgelehnt. |
KONFLIKT | Parallelitätskonflikt, z. B. Lese-, Änderungs- und Schreibkonflikt. Wird nur von einigen älteren Diensten verwendet. Die meisten Dienste verwenden stattdessen ABORTED oder ALREADY_EXISTS. Sehen Sie in der dienstspezifischen Dokumentation nach, welche davon in Ihrem Code behandelt werden soll. |
ABGEBROCHEN | Parallelitätskonflikt, z. B. Lese-, Änderungs- und Schreibkonflikt. |
IST BEREITS VORHANDEN | Die Ressource, die ein Client zu erstellen versuchte, ist bereits vorhanden. |
RESSOURCE_ERSCHÖPFT | Entweder ist das Ressourcenkontingent erschöpft oder die Ratenbegrenzung ist erreicht. |
ABGESAGT | Anfrage vom Kunden storniert. |
DATENVERLUST | Nicht behebbarer Datenverlust oder Datenbeschädigung. Der Client sollte den Fehler dem Benutzer melden. |
UNBEKANNT | Unbekannter Serverfehler. Typischerweise ein Serverfehler. Dieser Fehlercode wird auch Fehlern beim Parsen lokaler Antworten (Unmarshalieren) und einer Vielzahl anderer E/A-Fehler auf niedriger Ebene zugewiesen, die nicht leicht diagnostizierbar sind. |
INTERN | Interner Serverfehler. Typischerweise ein Serverfehler. |
NICHT VERFÜGBAR | Dienst nicht verfügbar. Normalerweise ist der Server vorübergehend ausgefallen. Dieser Fehlercode wird auch lokalen Netzwerkfehlern zugeordnet (Verbindung verweigert, keine Route zum Host). |
DEADLINE_EXCEEDED | Antragsfrist überschritten. Dies geschieht nur, wenn der Aufrufer eine Frist festlegt, die kürzer als die Standardfrist der Ziel-API ist (dh die angeforderte Frist reicht nicht aus, damit der Server die Anforderung verarbeiten kann) und die Anforderung nicht innerhalb der Frist abgeschlossen wurde. Dieser Fehlercode wird auch lokalen Verbindungs- und Lese-Timeouts zugewiesen. |
Die meisten APIs können nur zu einer Teilmenge der oben genannten Fehlercodes führen. In jedem Fall wird von Ihnen nicht erwartet, dass Sie alle diese Fehlercodes bei der Implementierung Ihrer Fehlerhandler explizit behandeln. Die meisten Anwendungen sind nur an ein bis zwei spezifischen Fehlercodes interessiert und behandeln alles andere als allgemeinen, nicht behebbaren Fehler.
Dienstspezifische Fehlercodes
Firebase-Auth
CERTIFICATE_FETCH_FAILED | Es konnten keine öffentlichen Schlüsselzertifikate abgerufen werden, die zur Überprüfung eines JWT (ID-Token oder Sitzungscookie) erforderlich sind. |
E-MAIL EXISTIERT BEREITS | Es existiert bereits ein Benutzer mit der angegebenen E-Mail-Adresse. |
EXPIRED_ID_TOKEN | Das für verifyIdToken() angegebene ID-Token ist abgelaufen. |
EXPIRED_SESSION_COOKIE | Das für verifySessionCookie() angegebene Sitzungscookie ist abgelaufen. |
INVALID_DYNAMIC_LINK_DOMAIN | Die bereitgestellte Dynamic-Link-Domäne ist für das aktuelle Projekt nicht konfiguriert oder autorisiert. Bezogen auf E-Mail-Aktionslink-APIs. |
INVALID_ID_TOKEN | Das für verifyIdToken() angegebene ID-Token ist ungültig. |
INVALID_SESSION_COOKIE | Das für verifySessionCookie() angegebene Sitzungscookie ist ungültig. |
PHONE_NUMBER_ALREADY_EXISTS | Es existiert bereits ein Benutzer mit der angegebenen Telefonnummer. |
REVOKED_ID_TOKEN | Das für verifyIdToken() angegebene ID-Token wird widerrufen. |
REVOKED_SESSION_COOKIE | Das für verifySessionCookie() angegebene Sitzungscookie ist abgelaufen. |
UNAUTHORIZED_CONTINUE_URL | Die Domäne der Fortsetzungs-URL steht nicht auf der Whitelist. Bezogen auf E-Mail-Aktionslink-APIs. |
BENUTZER NICHT GEFUNDEN | Für die angegebene Kennung wurde kein Benutzerdatensatz gefunden. |
Firebase Cloud-Messaging
THIRD_PARTY_AUTH_ERROR | Das APNs-Zertifikat oder der Web-Push-Authentifizierungs-API-Schlüssel war ungültig oder fehlte. |
UNGÜLTIGES ARGUMENT | Ein oder mehrere in der Anfrage angegebene Argumente waren ungültig. |
INTERN | Interner Serverfehler. |
QUOTE ÜBERSCHRITTEN | Das Sendelimit für das Nachrichtenziel wurde überschritten. |
SENDER_ID_MISMATCH | Die authentifizierte Absender-ID unterscheidet sich von der Absender-ID für das Registrierungstoken. Dies bedeutet normalerweise, dass sich der Absender und das Zielregistrierungstoken nicht im selben Firebase-Projekt befinden. |
NICHT VERFÜGBAR | Der Cloud Messaging-Dienst ist vorübergehend nicht verfügbar. |
NICHT REGISTRIERT | Die App-Instanz wurde von FCM abgemeldet. Dies bedeutet in der Regel, dass der verwendete Geräteregistrierungstoken nicht mehr gültig ist und ein neuer verwendet werden muss. |
Automatische Wiederholungsversuche
Das Admin SDK wiederholt automatisch bestimmte Fehler, bevor diese Fehler den Benutzern angezeigt werden. Im Allgemeinen werden die folgenden Arten von Fehlern transparent wiederholt:
- Alle API-Fehler, die aus HTTP 503-Antworten (Dienst nicht verfügbar) resultieren.
- Einige API-Fehler resultieren aus HTTP 500-Antworten (Internal Server Error).
- Die meisten E/A-Fehler auf niedriger Ebene (Verbindung abgelehnt, Verbindung zurückgesetzt usw.).
Das SDK wiederholt jeden der oben genannten Fehler bis zu fünf Mal (ursprünglicher Versuch + vier Wiederholungsversuche) mit exponentiellem Backoff. Sie können bei Bedarf Ihre eigenen Wiederholungsmechanismen auf Anwendungsebene implementieren, dies ist jedoch normalerweise nicht erforderlich.
Retry-After-Unterstützung
Die Go- und .NET-Implementierungen des Admin SDK unterstützen die Verarbeitung des HTTP- Retry-After
Headers. Das heißt, wenn die von den Back-End-Servern gesendete Fehlerantwort den standardmäßigen Retry-After
-Header enthält, berücksichtigt das SDK diesen beim erneuten Versuch, solange die angegebene Wartezeit nicht sehr lang ist. Wenn der Retry-After
Header eine sehr lange Wartezeit anzeigt, umgeht das SDK Wiederholungsversuche und löst den entsprechenden API-Fehler aus.
Das Python Admin SDK unterstützt derzeit nicht den Retry-After
Header und unterstützt nur einfaches exponentielles Backoff.
Beispiele für die API-Fehlerbehandlung
Implementierung eines generischen Fehlerhandlers
In den meisten Fällen benötigen Sie einen generischen Fehlerhandler, der ein breites Spektrum an Fehlern abfängt, um einen unerwarteten Abbruch des Programmablaufs aufgrund eines API-Fehlers zu verhindern. Solche Fehlerhandler protokollieren die Fehler normalerweise nur zu Prüfzwecken oder rufen eine andere Standardroutine zur Fehlerbehandlung für alle aufgetretenen API-Fehler auf. Sie interessieren sich nicht unbedingt für die unterschiedlichen Fehlercodes oder die Gründe, die den Fehler verursacht haben könnten.
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}')
Gehen
token, err := client.VerifyIDToken(ctx, idToken)
if err != nil {
log.Printf("Failed to verify ID token: %v", err)
return
}
performPrivilegedOperation(token)
.Netz
try
{
var token = await FirebaseAuth.DefaultInstance.VerifyIdTokenAsync(idToken);
PerformPrivilegedOperation(token.getUid());
}
catch (FirebaseAuthException ex)
{
Conole.WriteLine($"Failed to verify ID token: {ex.Message}");
}
Fehlercodes prüfen
In manchen Fällen möchten Sie die genauen Fehlercodes überprüfen und verschiedene kontextbezogene Fehlerbehandlungsroutinen aufrufen. Im folgenden Beispiel haben wir einen Fehlerhandler, der spezifischere Fehlermeldungen basierend auf dem Dienstfehlercode protokolliert.
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}')
Gehen
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)
.Netz
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}");
}
}
Hier ist ein weiteres Beispiel, bei dem wir sowohl nach Fehlercodes der obersten Ebene als auch nach Dienstfehlercodes suchen:
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}')
Gehen
_, 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
}
.Netz
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}");
}
}
Zugriff auf die HTTP-Antwort
In einigen seltenen Fällen möchten Sie möglicherweise die von einem Back-End-Dienst zurückgegebene HTTP-Fehlerantwort überprüfen und eine Fehlerbehandlungsaktion daran durchführen. Das Admin SDK stellt sowohl die Header als auch den Inhalt dieser Fehlerantworten bereit. Der Antwortinhalt wird normalerweise als Zeichenfolge oder rohe Bytesequenz zurückgegeben und kann in jedes erforderliche Zielformat geparst werden.
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}')
Gehen
_, 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
}
.Netz
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}");
}
}