Мы используем spring-cloud-starter-feign
с версией 1.3.5. ВЫПУСК.Недавно я получил странную проблему в производственной среде.Эта проблема не может быть воспроизведена в среде dev, test или stage.
Ошибка возникает в моем 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
, если используется ByteArrayBody
, body.length
получается из длины байтового массива.Это имеет значение, и я думаю, что это может быть основной причиной этой проблемы.
Итак, кто-нибудь может сказать мне, как притворно выбирать реализацию Response.Body
?
Любая помощь будет признательна.Заранее спасибо!