Feign Request returnType Response.class with "Transfer-Encoding: chunked"
See original GitHub issueWhy the reponse type is Response.class and feign.Response#body should not close when response data with header “Transfer-Encoding: chunked” and not contain “Content-Length”?
response.body().length() will return null and shouldClose variable will be set to false.
feign.AsyncResponseHandler#handleResponse
void handleResponse(CompletableFuture<Object> resultFuture,
String configKey,
Response response,
Type returnType,
long elapsedTime) {
// copied fairly liberally from SynchronousMethodHandler
boolean shouldClose = true;
try {
if (logLevel != Level.NONE) {
response = logger.logAndRebufferResponse(configKey, logLevel, response,
elapsedTime);
}
if (Response.class == returnType) {
if (response.body() == null) {
resultFuture.complete(response);
} else if (response.body().length() == null
|| response.body().length() > MAX_RESPONSE_BUFFER_SIZE) {
shouldClose = false;
resultFuture.complete(response);
} else {
// Ensure the response body is disconnected
final byte[] bodyData = Util.toByteArray(response.body().asInputStream());
resultFuture.complete(response.toBuilder().body(bodyData).build());
}
// ...
} catch (final IOException e) {
if (logLevel != Level.NONE) {
logger.logIOException(configKey, logLevel, e, elapsedTime);
}
resultFuture.completeExceptionally(errorReading(response.request(), response, e));
} catch (final Exception e) {
resultFuture.completeExceptionally(e);
} finally {
if (shouldClose) {
ensureClosed(response.body());
}
}
}
If I don’t use try-with-resource process response feign.Response#body,apache httpclient can’t re-use the connection,which waiting for get connection forever.
some tests which waiting for get connection forever:
public class ApacheHttpClientTest extends AbstractClientTest {
@Override
public Builder newBuilder() {
return Feign.builder().client(new ApacheHttpClient());
}
@Test
public void responseNotClose() {
final HttpClient httpClient = HttpClientBuilder.create()
.setMaxConnPerRoute(1)
.setMaxConnTotal(1)
.build();
final NoContentInterface testInterface = Feign.builder()
.client(new ApacheHttpClient(httpClient))
.target(NoContentInterface.class, "http://localhost:" + server.getPort());
server.enqueue(new MockResponse().setResponseCode(201).setChunkedBody("", -1));
server.enqueue(new MockResponse().setResponseCode(201).setChunkedBody("", -1));
Response res1 = testInterface.NoContent1("test1");
assertNotNull(res1);
System.out.println("waiting.....");
Response res2 = testInterface.NoContent1("test2");
assertNotNull(res2);
System.out.println("end.....");
}
public interface NoContentInterface {
@RequestLine("POST /no-content1")
Response NoContent1(@QueryParam("foo") String foo);
}
}
However, after I enable feign log output, feign.Logger#logAndRebufferResponse will rebuild response body with using feign.Util#toByteArray,feign.Response#body will consume and apache httpclient re-use this connection.
I don’t understand why it isn’t necessary to close feign.Response#body.If I enable feign log output, feign.Response#body is consumed in the end.
I think it should be also rebuild response body with using feign.Util#toByteArray .Look forward to your reply.
Issue Analytics
- State:
- Created 2 years ago
- Comments:7 (4 by maintainers)

Top Related StackOverflow Question
By obtaining the
Response, Feign relinquishes control to the caller, who is now responsible for handling the response, dealing with any errors, decoding the body, retrying, etc… This is the trade off for usingResponseobjects directly.This sounds like a bug, would you be able to create a minimal reproducible example and submit a new issue?