如何选择身体实现方式

时间:2018-09-29 08:05:56

标签: spring-cloud-feign

我们正在将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的实现,好像假装使用InputStreamBodybody.length()是从响应标头content-length获取的,如果{{使用1}},则ByteArrayBody是从字节数组长度中获得的。这有所作为,我想这可能是此问题的根本原因。

那么,谁能告诉我选择body.length实现有多大?

任何帮助将不胜感激。预先感谢!

0 个答案:

没有答案