那是一个非常古老的职位,但我遇到了类似的问题,我想与大家分享我的经验。
我正在使用其余的API构建微服务架构。我有一些其余的GET服务,它们根据请求参数从后端系统收集数据。
我遵循了其余的API设计文档,并且在没有符合查询条件的数据(例如,选择了零记录)时,我向HTTP 404发送了一条完美的JSON错误消息给客户端。
当没有数据要发送回客户端时,我准备了带有内部错误代码等的完美JSON消息,以通知客户端“未找到”的原因,并使用HTTP 404将其发送回客户端。工作良好。
后来,我创建了一个rest API客户端类,它是隐藏HTTP通信相关代码的简单帮手,当我从代码中调用我的rest API时,我一直都使用此帮手。
但是我只需要编写令人困惑的额外代码,因为HTTP 404具有两个不同的功能:
- 当剩余API在给定的URL中不可用时,它是真实的HTTP 404,它由运行剩余API应用程序的应用程序服务器或Web服务器抛出
- 当数据库中没有基于查询条件的数据时,客户端也将返回HTTP 404。
重要提示:我的rest API错误处理程序捕获了出现在后端服务中的所有异常,这意味着如果发生任何错误,我的rest API总是返回带有消息详细信息的完美JSON消息。
这是我的客户端帮助程序方法的第一个版本,它处理两个不同的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的情况下,我需要检查响应的主体。如果我可以解析响应主体,则可以确定我在哪里找到了响应没有数据发送回客户端。
如果我无法解析响应,则意味着我从Web服务器(而不是从其余API应用程序)获得了真实的HTTP 404。
这是如此令人困惑,并且客户端应用程序始终需要进行额外的分析才能检查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);
}
我认为这样可以更好地处理该问题。
如果您有更好的解决方案,请与我们分享。