我们正在将spring-cloud-starter-feign
用于1.3.5.RELEASE版本。最近,我在生产环境中遇到一个奇怪的问题。在开发,测试或阶段环境中无法复制此问题。
该错误在我的ErrorDecoder中引发。部分源代码粘贴在下面:
Body body = response.body();
JsonNode errorPayload = null;
String message = null;
if (body != null && body.length() != null && body.length() > 0) {
try (InputStream is = body.asInputStream()) {
errorPayload = mapper.readValue(is, JsonNode.class);
if (errorPayload.has("message")) {
message = errorPayload.get("message").asText();
}
} catch (IOException e) {
log.error("error while deserializing error payload", e);
throw new ClientParsingException();
}
}
switch (response.status()) {
case HttpStatus.SC_BAD_REQUEST:
if (errorPayload != null) {
if (errorPayload.has("error") && "invalid_grant".equals(errorPayload.get("error").asText())
&& "User account is locked".equals(errorPayload.get("error_description").asText())) {
throw new LockAccountException();
}
if (errorPayload.has("error") && "invalid_grant".equals(errorPayload.get("error").asText())) {
throw new BadCredentialsException();
}
// if not an authentication then it is a business error
JsonNode fieldErrorsPayload = errorPayload.path("fieldErrors");
List<FieldError> fieldErrors = new ArrayList<>();
fieldErrorsPayload.forEach(fieldError -> {
String objectName = fieldError.get("objectName").textValue();
String field = fieldError.get("field").textValue();
String fieldErrorMsg = fieldError.get("message").textValue();
fieldErrors.add(new FieldError(objectName, field, fieldErrorMsg));
});
log.debug("[{}]", fieldErrors);
throw new FieldListException(message, fieldErrors);
}
return errorStatus(methodKey, response);
//other casees
}
我在日志中得到的异常来自最后一个返回子句return errorStatus(methodKey, response);
,但是在错误消息中,打印了响应正文。
2018-09-29 07:49:30.228 ERROR 1 --- [ XNIO-2 task-5] io.undertow.request : UT005023: Exception handling request to /login
feign.FeignException: status 400 reading UaaService#authenticate(String,String); content:
{"error":"invalid_grant","error_description":"Bad credentials"}
at feign.FeignException.errorStatus(FeignException.java:62)
从错误日志中,我们可以发现响应主体不是空的,但它与我的代码中的逻辑冲突。因为只有当响应正文没有内容时,变量errorPayload
才会为null,因此可以打印此错误日志。
最后,我发现这可能是feign.Response.Body
的实现,好像假装使用InputStreamBody
,body.length()
是从响应标头content-length
获取的,如果{{使用1}},则ByteArrayBody
是从字节数组长度中获得的。这有所作为,我想这可能是此问题的根本原因。
那么,谁能告诉我选择body.length
实现有多大?
任何帮助将不胜感激。预先感谢!