Как Fegin выбрать реализацию Body - PullRequest
0 голосов
/ 29 сентября 2018

Мы используем 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?

Любая помощь будет признательна.Заранее спасибо!

...