Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue #1606 Customize the length of the body in FeignException builder #1767

Merged
merged 3 commits into from
Oct 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
46 changes: 36 additions & 10 deletions core/src/main/java/feign/FeignException.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ public class FeignException extends RuntimeException {
private static final String EXCEPTION_MESSAGE_TEMPLATE_NULL_REQUEST =
"request should not be null";
private static final long serialVersionUID = 0;
private int status;
private final int status;
private byte[] responseBody;
private Map<String, Collection<String>> responseHeaders;
private Request request;
private final Request request;

protected FeignException(int status, String message, Throwable cause) {
super(message, cause);
Expand Down Expand Up @@ -168,6 +168,13 @@ static FeignException errorReading(Request request, Response response, IOExcepti
}

public static FeignException errorStatus(String methodKey, Response response) {
return errorStatus(methodKey, response, null, null);
}

public static FeignException errorStatus(String methodKey,
Response response,
Integer maxBodyBytesLength,
Integer maxBodyCharsLength) {

byte[] body = {};
try {
Expand All @@ -180,6 +187,8 @@ public static FeignException errorStatus(String methodKey, Response response) {
String message = new FeignExceptionMessageBuilder()
.withResponse(response)
.withMethodKey(methodKey)
.withMaxBodyBytesLength(maxBodyBytesLength)
.withMaxBodyCharsLength(maxBodyCharsLength)
.withBody(body).build();

return errorStatus(response.status(), message, response.request(), body, response.headers());
Expand Down Expand Up @@ -423,6 +432,8 @@ private static class FeignExceptionMessageBuilder {

private byte[] body;
private String methodKey;
private Integer maxBodyBytesLength;
private Integer maxBodyCharsLength;

public FeignExceptionMessageBuilder withResponse(Response response) {
this.response = response;
Expand All @@ -439,9 +450,25 @@ public FeignExceptionMessageBuilder withMethodKey(String methodKey) {
return this;
}

public FeignExceptionMessageBuilder withMaxBodyBytesLength(Integer length) {
this.maxBodyBytesLength = length;
return this;
}

public FeignExceptionMessageBuilder withMaxBodyCharsLength(Integer length) {
this.maxBodyCharsLength = length;
return this;
}

public String build() {
StringBuilder result = new StringBuilder();

if (maxBodyBytesLength == null) {
maxBodyBytesLength = MAX_BODY_BYTES_LENGTH;
}
if (maxBodyCharsLength == null) {
maxBodyCharsLength = MAX_BODY_CHARS_LENGTH;
}
if (response.reason() != null) {
result.append(format("[%d %s]", response.status(), response.reason()));
} else {
Expand All @@ -455,32 +482,32 @@ public String build() {
return result.toString();
}

private static String getBodyAsString(byte[] body, Map<String, Collection<String>> headers) {
private String getBodyAsString(byte[] body, Map<String, Collection<String>> headers) {
Charset charset = getResponseCharset(headers);
if (charset == null) {
charset = Util.UTF_8;
}
return getResponseBody(body, charset);
}

private static String getResponseBody(byte[] body, Charset charset) {
if (body.length < MAX_BODY_BYTES_LENGTH) {
private String getResponseBody(byte[] body, Charset charset) {
if (body.length < maxBodyBytesLength) {
return new String(body, charset);
}
return getResponseBodyPreview(body, charset);
}

private static String getResponseBodyPreview(byte[] body, Charset charset) {
private String getResponseBodyPreview(byte[] body, Charset charset) {
try {
Reader reader = new InputStreamReader(new ByteArrayInputStream(body), charset);
CharBuffer result = CharBuffer.allocate(MAX_BODY_CHARS_LENGTH);
CharBuffer result = CharBuffer.allocate(maxBodyCharsLength);

reader.read(result);
reader.close();
((Buffer) result).flip();
return result.toString() + "... (" + body.length + " bytes)";
return result + "... (" + body.length + " bytes)";
} catch (IOException e) {
return e.toString() + ", failed to parse response";
return e + ", failed to parse response";
}
}

Expand All @@ -502,7 +529,6 @@ private static Charset getResponseCharset(Map<String, Collection<String>> header
return null;
}
return Charset.forName(group);

}
}
}
45 changes: 45 additions & 0 deletions core/src/test/java/feign/FeignExceptionTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,51 @@ public void canGetResponseHeadersFromException() {
});
}

@Test
public void lengthOfBodyExceptionTest() {
String bigResponse = "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";

Request request = Request.create(
Request.HttpMethod.GET,
"/home",
Collections.emptyMap(),
"data".getBytes(StandardCharsets.UTF_8),
StandardCharsets.UTF_8,
null);

Response response = Response.builder()
.status(400)
.request(request)
.body(bigResponse, StandardCharsets.UTF_8)
.build();

FeignException defaultException = FeignException.errorStatus("methodKey", response);
assertThat(defaultException.getMessage().length()).isLessThan(bigResponse.length());

FeignException customLengthBodyException =
FeignException.errorStatus("methodKey", response, 4000, 2000);
assertThat(customLengthBodyException.getMessage().length())
.isGreaterThanOrEqualTo(bigResponse.length());
}

@Test(expected = NullPointerException.class)
public void nullRequestShouldThrowNPEwThrowable() {
new Derived(404, "message", null, new Throwable());
Expand Down