Bu çok eski bir yazı ama benzer bir sorunla karşılaştım ve deneyimlerimi sizlerle paylaşmak istiyorum.
Ben dinlenme API'leri ile mikro hizmet mimarisi inşa ediyorum. Bazı dinlenme GET hizmetleri var, onlar istek parametrelerine dayalı arka uç sistemden veri toplamak.
Geri kalan API tasarım belgelerini takip ettim ve sorgu koşullarına uygun bir veri olmadığında (örneğin sıfır kayıt seçildi) HTTP 404'ü mükemmel bir JSON hata mesajıyla geri gönderdim.
Müşteriye geri gönderilecek veri olmadığında, müşteriyi "Bulunamadı" nedeni hakkında bilgilendirmek için dahili hata kodu vb. İle mükemmel bir JSON mesajı hazırladım ve HTTP 404 ile istemciye geri gönderildi. iyi çalışıyor.
Daha sonra HTTP iletişimiyle ilgili kodu gizlemek için kolay bir yardımcı olan bir dinlenme API istemci sınıfı oluşturduk ve bu yardımcıyı kodumdan kalan API'ları aradığımda her zaman kullandım.
AMA HTTP 404'ün iki farklı işlevi olduğu için kafa karıştırıcı ekstra kod yazmam gerekiyordu:
- dinlenme URL'si belirtilen url'de mevcut olmadığında gerçek HTTP 404, uygulama API'si veya dinlenme API uygulamasının çalıştığı web sunucusu tarafından atılır
- sorgunun nerede durumuna göre veritabanında veri olmadığında istemci HTTP 404'ü de geri alır.
Önemli: Dinlenme API'sı hata işleyicim tüm istisnaları yakalar, arka uç hizmetinde görünür, bu da herhangi bir hata durumunda dinlenme API'mın her zaman mesaj ayrıntılarıyla mükemmel bir JSON mesajı ile döndüğü anlamına gelir.
Bu, iki farklı HTTP 404 yanıtını işleyen istemci yardımcı yöntemimin 1. sürümüdür:
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");
}
AMA , Java veya JavaScript istemcim bir şekilde HTTP 404 iki tür alabilir çünkü HTTP 404 durumunda yanıt gövdesini kontrol etmek gerekir. Yanıt gövdesini ayrıştırabilirsem o zaman orada bir yanıt aldım eminim istemciye geri gönderilecek veri yok.
Ben yanıtı ayrıştırmak mümkün değilse, ben web sunucusundan gerçek bir HTTP 404 (geri kalan API uygulama değil) aldım anlamına gelir.
Bu çok kafa karıştırıcı ve istemci uygulamasının HTTP 404'ün gerçek nedenini kontrol etmek için her zaman ekstra ayrıştırma yapması gerekiyor.
Dürüst olmak gerekirse bu çözümü sevmiyorum. Kafa karıştırıcı, müşterilere her zaman ekstra saçma kodu eklemesi gerekiyor.
Bu yüzden bu iki farklı senaryoda HTTP 404 kullanmak yerine aşağıdakileri yapmaya karar verdim:
- Artık kalan uygulamada HTTP 404 yanıt HTTP kodu olarak kullanmıyorum.
- HTTP 404 yerine HTTP 204 (İçerik Yok) kullanacağım.
Bu durumda istemci kodu daha şık olabilir:
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);
}
Bence bu durum daha iyi işliyor.
Daha iyi bir çözümünüz varsa lütfen bizimle paylaşın.