这是一个非常老的帖子,但我也面临着类似的问题,我想与你们分享我的经验。
我正在用rest api构建微服务架构。我有一些rest GET服务,他们根据请求参数从后端系统收集数据。
我遵循其余的API设计文档,当没有符合查询条件的数据(例如零记录被选中)时,我向客户端发送了带有完美JSON错误消息的HTTP 404。
当没有数据要发送回客户端时,我准备了一个完美的JSON消息,包含内部错误代码等,以通知客户端“未找到”的原因,并将其与HTTP 404一起发送回客户端。这很好。
后来我创建了一个rest API客户端类,这是一个容易隐藏HTTP通信相关代码的助手,当我从我的代码调用我的rest API时,我一直使用这个助手。
但我需要编写令人困惑的额外代码,因为HTTP 404有两个不同的功能:
当rest API在给定的url中不可用时,真正的HTTP 404将由运行rest API应用程序的应用服务器或web服务器抛出
当数据库中没有数据时,客户端根据查询的where条件返回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 (No Content)而不是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);
}
我认为这能更好地解决这个问题。
如果你有更好的解决方案,请与我们分享。