ข้อผิดพลาด Admin SDK แบ่งออกเป็น 2 ประเภท:
- ข้อผิดพลาดในการเขียนโปรแกรม: นี่คือข้อผิดพลาดในการเขียนโปรแกรมและการกำหนดค่าในแอปพลิเคชันผู้ใช้ ส่วนใหญ่เกิดขึ้นเนื่องจากการใช้งาน SDK ไม่ถูกต้อง (เช่น การส่ง
null
ไปยังเมธอดที่ไม่ยอมรับค่าnull
) และข้อผิดพลาดในการกำหนดค่าอื่นๆ ที่โปรเจ็กต์ Firebase หรือระดับ SDK (ข้อมูลประจำตัวหายไป สตริงรหัสโปรเจ็กต์ไม่ถูกต้อง และอื่นๆ บน). - ข้อผิดพลาด 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 ประกอบด้วยองค์ประกอบต่อไปนี้:
- รหัสข้อผิดพลาด
- ข้อความผิดพลาด
- รหัสข้อผิดพลาดของบริการ (ไม่บังคับ)
- การตอบสนอง 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}");
}
}