การจัดการข้อผิดพลาดของผู้ดูแลระบบ SDK

ข้อผิดพลาด Admin SDK แบ่งออกเป็น 2 ประเภท:

  1. ข้อผิดพลาดในการเขียนโปรแกรม: นี่คือข้อผิดพลาดในการเขียนโปรแกรมและการกำหนดค่าในแอปพลิเคชันผู้ใช้ ส่วนใหญ่เกิดขึ้นเนื่องจากการใช้งาน SDK ไม่ถูกต้อง (เช่น การส่ง null ไปยังเมธอดที่ไม่ยอมรับค่า null ) และข้อผิดพลาดในการกำหนดค่าอื่นๆ ที่โปรเจ็กต์ Firebase หรือระดับ SDK (ข้อมูลประจำตัวหายไป สตริงรหัสโปรเจ็กต์ไม่ถูกต้อง และอื่นๆ บน).
  2. ข้อผิดพลาด API: ซึ่งรวมถึงข้อผิดพลาดที่สามารถกู้คืนได้ต่างๆ ที่เกิดขึ้นภายในการใช้งาน SDK ข้อผิดพลาดทั้งหมดที่เกิดขึ้นในบริการแบ็กเอนด์ของ Firebase และข้อผิดพลาดชั่วคราวอื่นๆ (เช่น การหมดเวลา) ที่อาจเกิดขึ้นขณะทำการเรียก RPC

Admin SDK จะส่งสัญญาณ ข้อผิดพลาดในการเขียนโปรแกรม โดยส่งข้อผิดพลาดที่เกิดจากแพลตฟอร์มที่เป็นปัญหา

  • Java: ส่งอินสแตนซ์ของ IllegalArgumentException , NullPointerException หรือประเภทข้อผิดพลาดรันไทม์ในตัวที่คล้ายกัน
  • Python: เพิ่มอินสแตนซ์ของ ValueError , TypeError หรือประเภทข้อผิดพลาดในตัวอื่นๆ
  • ไป: ส่งกลับข้อผิดพลาดทั่วไป
  • .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 ข้อผิดพลาดเหล่านี้บางส่วนสามารถกู้คืนได้ เช่น ข้อผิดพลาดที่เป็นผลมาจากบริการที่ไม่สามารถใช้งานได้ชั่วคราว และข้อผิดพลาดบางส่วนอาจเกิดขึ้นได้ในระหว่างขั้นตอนการทำงานของโปรแกรมปกติ เช่น การตรวจพบโทเค็น ID ที่ไม่ถูกต้องหรือหมดอายุ คู่มือส่วนที่เหลือนี้จะสรุปวิธีที่ Admin SDK แสดงถึงข้อผิดพลาดของ API ดังกล่าว และตัวเลือกต่างๆ ที่พร้อมใช้งานสำหรับการจัดการข้อผิดพลาดเหล่านั้น

โครงสร้างของข้อผิดพลาด API

ข้อผิดพลาด API ประกอบด้วยองค์ประกอบต่อไปนี้:

  1. รหัสข้อผิดพลาด
  2. ข้อความผิดพลาด
  3. รหัสข้อผิดพลาดของบริการ (ไม่บังคับ)
  4. การตอบสนอง HTTP (ไม่บังคับ)

รับประกันว่าข้อผิดพลาด API ทุกรายการจะมีรหัสข้อผิดพลาดและข้อความแสดงข้อผิดพลาด ข้อผิดพลาด API บางอย่างยังมีรหัสข้อผิดพลาดของบริการที่เฉพาะเจาะจงสำหรับ API ที่สร้างข้อผิดพลาด ตัวอย่างเช่น ข้อผิดพลาดบางอย่างที่สร้างโดย Firebase Auth API มีรหัสข้อผิดพลาดของบริการที่เฉพาะเจาะจงสำหรับ Firebase Auth หากข้อผิดพลาดเป็นผลมาจากการตอบสนองข้อผิดพลาด HTTP จากบริการแบ็กเอนด์ ข้อผิดพลาด API ก็จะมีการตอบกลับ HTTP ที่เกี่ยวข้องด้วย ซึ่งสามารถใช้เพื่อตรวจสอบส่วนหัวและเนื้อหาที่แน่นอนของการตอบกลับดั้งเดิม ซึ่งมีประโยชน์สำหรับการดีบัก การบันทึก หรือการนำตรรกะการจัดการข้อผิดพลาดที่ซับซ้อนมากขึ้นไปใช้

การใช้งาน Admin SDK ทั้งหมดยกเว้น Node.js มี API ที่ช่วยให้สามารถเข้าถึงส่วนประกอบข้างต้นของข้อผิดพลาด API

ประเภทข้อผิดพลาดและ API ตามภาษา

ชวา

ใน Java ข้อผิดพลาด 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 คลาส 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 หากอาร์กิวเมนต์อินพุตมีรหัสข้อผิดพลาดที่ต้องการ และส่งคืน false สำหรับอย่างอื่นทั้งหมด ฟังก์ชัน HTTPResponse() มีลักษณะการทำงานที่คล้ายกัน ยกเว้นว่าจะคืนค่า nil แทนที่จะเป็น false

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 ได้รับการประกาศให้ Throw อินสแตนซ์ของ FirebaseAuthException คุณสามารถเข้าถึงรหัสข้อผิดพลาดของบริการได้จากคลาสที่ได้รับนี้

public class FirebaseAuthException : FirebaseException {

    public AuthErrorCode AuthErrorCode { get; }
}

รหัสข้อผิดพลาดของแพลตฟอร์ม

รหัสข้อผิดพลาดเป็นเรื่องปกติในบริการ Firebase และ Google Cloud Platform ทั้งหมด ตารางต่อไปนี้สรุปรหัสข้อผิดพลาดของแพลตฟอร์มที่เป็นไปได้ทั้งหมด นี่เป็นรายการที่มีเสถียรภาพ และคาดว่าจะไม่มีการเปลี่ยนแปลงเป็นระยะเวลานาน

INVALID_ARGUMENT ลูกค้าระบุอาร์กิวเมนต์ที่ไม่ถูกต้อง
FAILED_PRCONDITION ไม่สามารถดำเนินการคำขอได้ในสถานะระบบปัจจุบัน เช่น การลบไดเร็กทอรีที่ไม่ว่างเปล่า
ไม่อยู่ในขอบเขต ลูกค้าระบุช่วงที่ไม่ถูกต้อง
ไม่ได้รับอนุญาต คำขอไม่ได้รับการตรวจสอบสิทธิ์เนื่องจากโทเค็น OAuth หายไป ไม่ถูกต้อง หรือหมดอายุ
สิทธิ์_ปฏิเสธ ลูกค้าไม่ได้รับอนุญาตเพียงพอ กรณีนี้อาจเกิดขึ้นได้เนื่องจากโทเค็น OAuth ไม่มีขอบเขตที่ถูกต้อง ไคลเอ็นต์ไม่มีสิทธิ์ หรือไม่ได้เปิดใช้ API สำหรับโปรเจ็กต์ไคลเอ็นต์
ไม่พบ ไม่พบทรัพยากรที่ระบุ หรือคำขอถูกปฏิเสธเนื่องจากเหตุผลที่ไม่เปิดเผย เช่น การอนุญาตพิเศษ
ขัดแย้ง ข้อขัดแย้งที่เกิดขึ้นพร้อมกัน เช่น ข้อขัดแย้งในการอ่าน-แก้ไข-เขียน ใช้โดยบริการดั้งเดิมเพียงไม่กี่รายการเท่านั้น บริการส่วนใหญ่ใช้ ABORTED หรือ ALREADY_EXISTS แทน โปรดดูเอกสารเฉพาะบริการเพื่อดูว่าต้องจัดการเอกสารใดในโค้ดของคุณ
ถูกยกเลิก ข้อขัดแย้งที่เกิดขึ้นพร้อมกัน เช่น ข้อขัดแย้งในการอ่าน-แก้ไข-เขียน
มีอยู่แล้ว ทรัพยากรที่ไคลเอนต์พยายามสร้างมีอยู่แล้ว
ทรัพยากร_หมดสิ้นแล้ว โควต้าทรัพยากรไม่เพียงพอหรือถึงขีดจำกัดอัตรา
ยกเลิก คำขอถูกยกเลิกโดยลูกค้า
ข้อมูล_สูญหาย ข้อมูลสูญหายหรือเสียหายของข้อมูลที่ไม่สามารถกู้คืนได้ ลูกค้าควรรายงานข้อผิดพลาดให้กับผู้ใช้
ไม่ทราบ ข้อผิดพลาดเซิร์ฟเวอร์ที่ไม่รู้จัก โดยทั่วไปแล้วข้อผิดพลาดของเซิร์ฟเวอร์

รหัสข้อผิดพลาดนี้ยังถูกกำหนดให้กับข้อผิดพลาดในการแยกวิเคราะห์การตอบสนองในเครื่อง (unmarshal) และข้อผิดพลาด I/O ระดับต่ำอื่นๆ มากมายที่ไม่สามารถวินิจฉัยได้ง่าย

ภายใน ข้อผิดพลาดเซิร์ฟเวอร์ภายใน โดยทั่วไปแล้วข้อผิดพลาดของเซิร์ฟเวอร์
ไม่สามารถใช้ได้ ไม่สามารถให้บริการได้. โดยปกติแล้วเซิร์ฟเวอร์จะหยุดทำงานชั่วคราว

รหัสข้อผิดพลาดนี้ยังถูกกำหนดให้กับข้อผิดพลาดของเครือข่ายท้องถิ่นด้วย (การเชื่อมต่อถูกปฏิเสธ ไม่มีเส้นทางไปยังโฮสต์)

DEADLINE_EXCEEDED เกินกำหนดเวลาคำขอแล้ว สิ่งนี้จะเกิดขึ้นเฉพาะในกรณีที่ผู้เรียกกำหนดกำหนดเวลาที่สั้นกว่ากำหนดเวลาเริ่มต้นของ API เป้าหมาย (เช่น กำหนดเวลาที่ร้องขอไม่เพียงพอสำหรับเซิร์ฟเวอร์ในการประมวลผลคำขอ) และคำขอไม่เสร็จสิ้นภายในกำหนดเวลา

รหัสข้อผิดพลาดนี้ยังถูกกำหนดให้กับการเชื่อมต่อภายในเครื่องและการหมดเวลาการอ่านอีกด้วย

API ส่วนใหญ่สามารถส่งผลให้เกิดชุดย่อยของรหัสข้อผิดพลาดข้างต้นเท่านั้น ไม่ว่าในกรณีใด คุณไม่คาดหวังให้จัดการรหัสข้อผิดพลาดเหล่านี้ทั้งหมดอย่างชัดเจนเมื่อใช้งานตัวจัดการข้อผิดพลาดของคุณ แอปพลิเคชันส่วนใหญ่จะสนใจเฉพาะรหัสข้อผิดพลาด 1-2 รหัสเท่านั้น และถือว่าทุกอย่างเป็นความล้มเหลวทั่วไปและไม่สามารถกู้คืนได้

รหัสข้อผิดพลาดเฉพาะบริการ

การตรวจสอบสิทธิ์ Firebase

CERTIFICATE_FETCH_FAILED ไม่สามารถดึงใบรับรองคีย์สาธารณะที่จำเป็นในการตรวจสอบ JWT (โทเค็น ID หรือคุกกี้เซสชัน)
EMAIL_ALREADY_EXISTS มีผู้ใช้อยู่แล้วด้วยอีเมลที่ให้ไว้
EXPIRED_ID_TOKEN โทเค็น ID ที่ระบุเพื่อ verifyIdToken() หมดอายุแล้ว
EXPIRED_SESSION_COOKIE คุกกี้เซสชันที่ระบุเพื่อ verifySessionCookie() iis หมดอายุแล้ว
INVALID_DYNAMIC_LINK_DOMAIN โดเมนลิงก์แบบไดนามิกที่ให้มาไม่ได้รับการกำหนดค่าหรือได้รับอนุญาตสำหรับโครงการปัจจุบัน เกี่ยวข้องกับ API ลิงก์การดำเนินการอีเมล
INVALID_ID_TOKEN โทเค็น ID ที่ระบุเพื่อ verifyIdToken() ไม่ถูกต้อง
INVALID_SESSION_COOKIE คุกกี้เซสชันที่ระบุเพื่อ verifySessionCookie() ไม่ถูกต้อง
PHONE_NUMBER_ALREADY_EXISTS มีผู้ใช้อยู่แล้วโดยใช้หมายเลขโทรศัพท์ที่ให้ไว้
REVOKED_ID_TOKEN โทเค็น ID ที่ระบุเพื่อ verifyIdToken() ถูกเพิกถอนแล้ว
REVOKED_SESSION_COOKIE คุกกี้เซสชันที่ระบุเพื่อ verifySessionCookie() หมดอายุแล้ว
UNAUTHORIZED_CONTINUE_URL โดเมนของ URL ดำเนินการต่อไม่ได้อยู่ในรายการที่อนุญาตพิเศษ เกี่ยวข้องกับ API ลิงก์การดำเนินการอีเมล
ไม่พบชื่อผู้ใช้ ไม่พบบันทึกผู้ใช้สำหรับตัวระบุที่กำหนด

การส่งข้อความบนคลาวด์ของ Firebase

THIRD_PARTY_AUTH_ERROR ใบรับรอง APN หรือคีย์ Web Push Auth API ไม่ถูกต้องหรือหายไป
INVALID_ARGUMENT อาร์กิวเมนต์อย่างน้อยหนึ่งรายการที่ระบุในคำขอไม่ถูกต้อง
ภายใน ข้อผิดพลาดเซิร์ฟเวอร์ภายใน
QUOTA_EXCEEDED เกินขีดจำกัดการส่งสำหรับเป้าหมายข้อความ
SENDER_ID_MISMATCH ID ผู้ส่งที่ได้รับการรับรองความถูกต้องจะแตกต่างจาก ID ผู้ส่งสำหรับโทเค็นการลงทะเบียน ซึ่งโดยปกติหมายความว่าผู้ส่งและโทเค็นการลงทะเบียนเป้าหมายไม่ได้อยู่ในโปรเจ็กต์ 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 และรองรับเฉพาะการแบ็คออฟแบบเอ็กซ์โปเนนเชียลแบบธรรมดาเท่านั้น

ตัวอย่างการจัดการข้อผิดพลาด 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}");
}

กำลังตรวจสอบรหัสข้อผิดพลาด

ในบางกรณี คุณต้องการตรวจสอบรหัสข้อผิดพลาดที่แน่นอน และเรียกใช้รูทีนการจัดการข้อผิดพลาดแบบ Context-Aware ที่แตกต่างกัน ในตัวอย่างต่อไปนี้ เรามีตัวจัดการข้อผิดพลาดที่บันทึกข้อความแสดงข้อผิดพลาดที่เฉพาะเจาะจงมากขึ้นโดยยึดตามรหัสข้อผิดพลาดของบริการ

ชวา

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