diff --git a/core/src/main/java/feign/codec/ErrorDecoder.java b/core/src/main/java/feign/codec/ErrorDecoder.java index 6facb2b2d..280bdf28e 100644 --- a/core/src/main/java/feign/codec/ErrorDecoder.java +++ b/core/src/main/java/feign/codec/ErrorDecoder.java @@ -83,13 +83,26 @@ public interface ErrorDecoder { */ public Exception decode(String methodKey, Response response); - public static class Default implements ErrorDecoder { + public class Default implements ErrorDecoder { private final RetryAfterDecoder retryAfterDecoder = new RetryAfterDecoder(); + private Integer maxBodyBytesLength; + private Integer maxBodyCharsLength; + + public Default() { + this.maxBodyBytesLength = null; + this.maxBodyCharsLength = null; + } + + public Default(Integer maxBodyBytesLength, Integer maxBodyCharsLength) { + this.maxBodyBytesLength = maxBodyBytesLength; + this.maxBodyCharsLength = maxBodyCharsLength; + } @Override public Exception decode(String methodKey, Response response) { - FeignException exception = errorStatus(methodKey, response); + FeignException exception = errorStatus(methodKey, response, maxBodyBytesLength, + maxBodyCharsLength); Date retryAfter = retryAfterDecoder.apply(firstOrNull(response.headers(), RETRY_AFTER)); if (retryAfter != null) { return new RetryableException( diff --git a/core/src/test/java/feign/codec/DefaultErrorDecoderTest.java b/core/src/test/java/feign/codec/DefaultErrorDecoderTest.java index c6b0ffeba..712a2ebb6 100644 --- a/core/src/test/java/feign/codec/DefaultErrorDecoderTest.java +++ b/core/src/test/java/feign/codec/DefaultErrorDecoderTest.java @@ -21,8 +21,11 @@ import feign.Request.HttpMethod; import feign.Response; import feign.Util; +import java.io.ByteArrayInputStream; +import java.io.InputStream; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; import org.junit.Rule; @@ -135,4 +138,53 @@ public void retryAfterHeaderThrowsRetryableException() throws Throwable { throw errorDecoder.decode("Service#foo()", response); } + + @Test + public void lengthOfBodyExceptionTest() { + Response response = bigBodyResponse(); + Exception defaultException = errorDecoder.decode("Service#foo()", response); + assertThat(defaultException.getMessage().length()).isLessThan(response.body().length()); + + ErrorDecoder customizedErrorDecoder = new ErrorDecoder.Default(4000, 2000); + Exception customizedException = customizedErrorDecoder.decode("Service#foo()", response); + assertThat(customizedException.getMessage().length()) + .isGreaterThanOrEqualTo(response.body().length()); + } + + private Response bigBodyResponse() { + String content = "I love a storm in early May\n" + + "When springtime’s boisterous, firstborn thunder\n" + + "Over the sky will gaily wander\n" + + "And growl and roar as though in play.\n" + + "\n" + + "A peal, another — gleeful, cheering…\n" + + "Rain, raindust… On the trees, behold!-\n" + + "The drops hang, each a long pearl earring;\n" + + "Bright sunshine paints the thin threads gold.\n" + + "\n" + + "A stream downhill goes rushing reckless,\n" + + "And in the woods the birds rejoice.\n" + + "Din. Clamour. Noise. All nature echoes\n" + + "The thunder’s youthful, merry voice.\n" + + "\n" + + "You’ll say: ‘Tis laughing, carefree Hebe —\n" + + "She fed her father’s eagle, and\n" + + "The Storm Cup brimming with a seething\n" + + "And bubbling wine dropped from her hand"; + + InputStream inputStream = new ByteArrayInputStream(content.getBytes(UTF_8)); + Map> headers = new HashMap>(); + headers.put("Content-Type", Collections.singleton("text/plain")); + return Response.builder() + .status(400) + .request(Request.create( + Request.HttpMethod.GET, + "/home", + Collections.emptyMap(), + "data".getBytes(Util.UTF_8), + Util.UTF_8, + null)) + .body(content, Util.UTF_8) + .build(); + } }