นั่นคือโพสต์เก่ามาก แต่ฉันต้องเผชิญกับปัญหาที่คล้ายกันและฉันต้องการแบ่งปันประสบการณ์ของฉันกับพวกคุณ
ฉันกำลังสร้างสถาปัตยกรรมไมโครเซอร์วิสด้วย API ส่วนที่เหลือ ฉันมีบริการ GET ที่เหลือพวกเขารวบรวมข้อมูลจากระบบแบ็คเอนด์ตามพารามิเตอร์คำขอ
ฉันติดตามเอกสารการออกแบบ API ส่วนที่เหลือและฉันส่ง HTTP 404 กลับพร้อมข้อความข้อผิดพลาด JSON ที่สมบูรณ์แบบให้กับลูกค้าเมื่อไม่มีข้อมูลที่สอดคล้องกับเงื่อนไขการสืบค้น (ตัวอย่างเช่นเลือกบันทึกศูนย์)
เมื่อไม่มีข้อมูลที่จะส่งกลับไปยังลูกค้าฉันได้เตรียมข้อความ JSON ที่สมบูรณ์พร้อมรหัสข้อผิดพลาดภายในและอื่น ๆ เพื่อแจ้งลูกค้าเกี่ยวกับสาเหตุของการ "ไม่พบ" และมันถูกส่งกลับไปยังไคลเอนต์ด้วย HTTP 404 ทำงานได้ดี
ต่อมาฉันได้สร้างคลาสไคลเอนต์ API ที่เหลือซึ่งเป็นผู้ช่วยที่ง่ายในการซ่อนรหัสที่เกี่ยวข้องกับการสื่อสาร HTTP และฉันใช้ตัวช่วยนี้ตลอดเวลาเมื่อฉันเรียก API ที่เหลือของฉันจากรหัสของฉัน
แต่ฉันต้องการเขียนโค้ดพิเศษที่สับสนเพียงเพราะ HTTP 404 มีฟังก์ชันที่แตกต่างกันสองประการ:
- HTTP 404 จริงเมื่อ API ส่วนที่เหลือไม่พร้อมใช้งานใน URL ที่กำหนดซึ่งจะถูกโยนโดยแอ็พพลิเคชันเซิร์ฟเวอร์หรือเว็บเซิร์ฟเวอร์ที่แอปพลิเคชัน API ส่วนที่เหลือทำงาน
- ไคลเอนต์รับ HTTP 404 กลับเช่นกันเมื่อไม่มีข้อมูลในฐานข้อมูลตามเงื่อนไขการค้นหา
สำคัญ: ตัวจัดการข้อผิดพลาด API ส่วนที่เหลือของฉันจะจับข้อยกเว้นทั้งหมดที่ปรากฏในบริการแบ็คเอนด์ซึ่งหมายความว่าในกรณีที่มีข้อผิดพลาด API ส่วนที่เหลือของฉันจะกลับมาพร้อมกับข้อความ JSON ที่สมบูรณ์พร้อมรายละเอียดข้อความ
นี่เป็นรุ่นที่ 1 ของวิธีผู้ช่วยลูกค้าของฉันซึ่งรองรับการตอบสนอง HTTP 404 ที่ต่างกันสองรายการ:
public static String getSomething(final String uuid) {
String serviceUrl = getServiceUrl();
String path = "user/" + , uuid);
String requestUrl = serviceUrl + path;
String httpMethod = "GET";
Response response = client
.target(serviceUrl)
.path(path)
.request(ExtendedMediaType.APPLICATION_UTF8)
.get();
if (response.getStatus() == Response.Status.OK.getStatusCode()) {
// HTTP 200
return response.readEntity(String.class);
} else {
// confusing code comes here just because
// I need to decide the type of HTTP 404...
// trying to parse response body
try {
String responseBody = response.readEntity(String.class);
ObjectMapper mapper = new ObjectMapper();
ErrorInfo errorInfo = mapper.readValue(responseBody, ErrorInfo.class);
// re-throw the original exception
throw new MyException(errorInfo);
} catch (IOException e) {
// this is a real HTTP 404
throw new ServiceUnavailableError(response, requestUrl, httpMethod);
}
// this exception will never be thrown
throw new Exception("UNEXPECTED ERRORS, BETTER IF YOU DO NOT SEE IT IN THE LOG");
}
แต่เนื่องจากไคลเอนต์ Java หรือ JavaScript ของฉันสามารถรับ HTTP 404 สองชนิดฉันต้องตรวจสอบเนื้อหาของการตอบสนองในกรณีของ HTTP 404 หากฉันสามารถแยกวิเคราะห์เนื้อหาการตอบกลับได้ฉันแน่ใจว่าฉันได้รับการตอบกลับเมื่อมี ไม่มีข้อมูลที่จะส่งกลับไปยังลูกค้า
ถ้าฉันไม่สามารถแยกการตอบสนองนั่นหมายความว่าฉันได้รับ HTTP 404 จริงจากเว็บเซิร์ฟเวอร์ (ไม่ใช่จากแอปพลิเคชัน API ที่เหลือ)
มันสับสนมากและแอปพลิเคชันไคลเอนต์ต้องทำการวิเคราะห์คำพิเศษเพิ่มเติมเพื่อตรวจสอบเหตุผลที่แท้จริงของ HTTP 404
สุจริตฉันไม่ชอบวิธีนี้ มันสับสนต้องเพิ่มรหัสพล่ามให้กับลูกค้าตลอดเวลา
ดังนั้นแทนที่จะใช้ HTTP 404 ในสองสถานการณ์นี้ฉันจึงตัดสินใจว่าจะทำสิ่งต่อไปนี้:
- ฉันไม่ได้ใช้ HTTP 404 เป็นรหัสการตอบสนอง HTTP ในแอปพลิเคชันที่เหลือของฉันอีกต่อไป
- ฉันจะใช้ HTTP 204 (ไม่มีเนื้อหา) แทน HTTP 404
ในกรณีที่รหัสลูกค้าอาจสง่างามกว่า:
public static String getString(final String processId, final String key) {
String serviceUrl = getServiceUrl();
String path = String.format("key/%s", key);
String requestUrl = serviceUrl + path;
String httpMethod = "GET";
log(requestUrl);
Response response = client
.target(serviceUrl)
.path(path)
.request(ExtendedMediaType.APPLICATION_JSON_UTF8)
.header(CustomHttpHeader.PROCESS_ID, processId)
.get();
if (response.getStatus() == Response.Status.OK.getStatusCode()) {
return response.readEntity(String.class);
} else {
String body = response.readEntity(String.class);
ObjectMapper mapper = new ObjectMapper();
ErrorInfo errorInfo = mapper.readValue(body, ErrorInfo.class);
throw new MyException(errorInfo);
}
throw new AnyServerError(response, requestUrl, httpMethod);
}
ฉันคิดว่าสิ่งนี้จะจัดการกับปัญหาได้ดีกว่า
หากคุณมีทางออกที่ดีกว่านี้โปรดแบ่งปันกับเรา