Đó là một bài viết rất cũ nhưng tôi đã đối mặt với một vấn đề tương tự và tôi muốn chia sẻ kinh nghiệm của tôi với các bạn.
Tôi đang xây dựng kiến trúc microservice với các API còn lại. Tôi có một số dịch vụ GET còn lại, họ thu thập dữ liệu từ hệ thống back-end dựa trên các tham số yêu cầu.
Tôi đã theo dõi các tài liệu thiết kế API còn lại và tôi đã gửi lại HTTP 404 với thông báo lỗi JSON hoàn hảo cho khách hàng khi không có dữ liệu nào phù hợp với các điều kiện truy vấn (ví dụ: không có bản ghi nào được chọn).
Khi không có dữ liệu để gửi lại cho khách hàng, tôi đã chuẩn bị một thông báo JSON hoàn hảo với mã lỗi nội bộ, v.v. để thông báo cho khách hàng về lý do của "Không tìm thấy" và nó đã được gửi lại cho khách hàng với HTTP 404. Điều đó hoạt động tốt
Sau đó, tôi đã tạo một lớp máy khách API còn lại, một trình trợ giúp dễ dàng để ẩn mã liên quan đến giao tiếp HTTP và tôi đã sử dụng trình trợ giúp này mọi lúc khi tôi gọi các API còn lại từ mã của mình.
NHƯNG tôi cần phải viết thêm mã khó hiểu chỉ vì HTTP 404 có hai chức năng khác nhau:
- HTTP 404 thực khi API còn lại không có sẵn trong url đã cho, nó được ném bởi máy chủ ứng dụng hoặc máy chủ web nơi ứng dụng API còn lại chạy
- khách hàng cũng nhận lại HTTP 404 khi không có dữ liệu trong cơ sở dữ liệu dựa trên điều kiện truy vấn.
Quan trọng: Trình xử lý lỗi API còn lại của tôi nắm bắt tất cả các ngoại lệ xuất hiện trong dịch vụ back-end, nghĩa là trong trường hợp có bất kỳ lỗi nào, API còn lại của tôi luôn trả về với một thông báo JSON hoàn hảo với các chi tiết thông báo.
Đây là phiên bản đầu tiên của phương thức trợ giúp khách hàng của tôi xử lý hai phản hồi HTTP 404 khác nhau:
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");
}
NHƯNG , bởi vì máy khách Java hoặc JavaScript của tôi có thể nhận được hai loại HTTP 404 bằng cách nào đó tôi cần kiểm tra phần thân của phản hồi trong trường hợp HTTP 404. Nếu tôi có thể phân tích phần thân phản hồi thì tôi chắc chắn rằng tôi đã nhận được phản hồi khi có không có dữ liệu để gửi lại cho khách hàng
Nếu tôi không thể phân tích cú pháp phản hồi, điều đó có nghĩa là tôi đã lấy lại HTTP 404 thực từ máy chủ web (không phải từ ứng dụng API còn lại).
Điều này thật khó hiểu và ứng dụng khách luôn cần phải phân tích cú pháp thêm để kiểm tra lý do thực sự của HTTP 404.
Thành thật mà nói tôi không thích giải pháp này. Thật khó hiểu, cần phải thêm mã nhảm nhí cho khách hàng mọi lúc.
Vì vậy, thay vì sử dụng HTTP 404 trong hai kịch bản khác nhau này, tôi đã quyết định rằng tôi sẽ làm như sau:
- Tôi không sử dụng HTTP 404 làm mã HTTP phản hồi trong ứng dụng còn lại của mình nữa.
- Tôi sẽ sử dụng HTTP 204 (Không có nội dung) thay vì HTTP 404.
Trong trường hợp đó, mã khách hàng có thể thanh lịch hơn:
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);
}
Tôi nghĩ rằng điều này xử lý vấn đề đó tốt hơn.
Nếu bạn có bất kỳ giải pháp tốt hơn xin vui lòng chia sẻ nó với chúng tôi.