-
Notifications
You must be signed in to change notification settings - Fork 38.5k
Disable streaming when reading to Resources in RestTemplate [SPR-14882] #19448
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
Comments
Hadrien Kohl commented Hi, I am having trouble running the spring project tests on my machine so I am copy pasting the code I came up with: **
* @author Arjen Poutsma
* @author Rossen Stoyanchev
*/
@SuppressWarnings("unchecked")
public class RestTemplateTests {
// [...]
@Test // SPR-14882
public void shouldLeaveInputStreamOpenIfResourceInputStream() throws IOException, URISyntaxException {
ByteArrayInputStream stream = spy(
new ByteArrayInputStream("Spring".getBytes(Charset.defaultCharset()))
);
InputStreamResource resource = new InputStreamResource(stream);
given(requestFactory.createRequest(new URI("http://example.com/stream"), HttpMethod.GET))
.willReturn(request);
given(request.execute()).willReturn(response);
given(converter.canRead(InputStreamResource.class, MediaType.TEXT_PLAIN)).willReturn(true);
given(converter.read(eq(InputStreamResource.class), any(HttpInputMessage.class))).willReturn(resource);
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.setContentType(MediaType.TEXT_PLAIN);
responseHeaders.setContentLength(10);
given(response.getStatusCode()).willReturn(HttpStatus.OK);
given(response.getHeaders()).willReturn(responseHeaders);
given(response.getBody()).willReturn(stream);
resource = template.getForObject("http://example.com/stream", InputStreamResource.class);
verify(stream, never()).close();
resource.getInputStream().close();
verify(stream).close();
}
} |
Hadrien Kohl commented I am wondering if I am pushing the client to its limit actually. I made tests setting up a SimpleClientHttpRequestFactory with setBufferRequestBody(false) and it seems to run correctly, meaning that the body stream is not closed. Still, allowing the RestTemplate to return InputStreamResource yet closing it was very hard to predict from the documentation. |
Brian Clozel commented The goal of the change in The problem with your use case is that you're implicitly using the Now disabling buffering in the response with So in summary:
Unless I'm missing something, both The only improvement I could see is to prevent that use case with What do you think? |
Jörn Horstmann commented I'm also running into an issue with According to the last paragraph on http://docs.oracle.com/javase/8/docs/technotes/guides/net/http-keepalive.html, closing the
There is a discussion about the implementation at http://stackoverflow.com/questions/14378908/java-httpurlconnection-inputstream-close-hangs-or-works-too-long which shows that it also only tries to consume immediately I have two open issues in my project about this problem, zalando-nakadi/fahrschein#83 and zalando-nakadi/fahrschein#17, the latter one about similar behaviour with the apache http components implementation. To really solve the issue, there would need to be two
|
Brian Clozel commented To complete my previous comment:
Of course, you can write your own Jörn Horstmann, I understand the rationale behind your proposal but that would go against the Note that we're working on a new |
Jörn Horstmann commented
Note that I'm not using |
vivek sanhai commented if this fix will disable Streaming in Rest Template while reading large files what are my options to call a Rest API that returns Large File and if I need to use Spring 4.x in my project?
|
Brian Clozel commented This fix has been applied to Spring Framework 5.0. If you're using a 4.x version, this does not apply to you. When you'll switch to 5.x, using |
Hadrien Kohl opened SPR-14882 and commented
This issue has been updated to reflect the actual outcome of the discussion. See next section and comments for the original report.
The
ResourceHttpMessageConverter
supports converting from anHttpInputMessage
to anInputStreamResource
. This is valid when reading resources on the server side, but it's not compatible with the wayRestTemplate
works.The API exposed by
RestOperations
imply that the HTTP server response should be fully consumed and properly closed by the time theexchange
method returns. In other words, this HTTP client does not support streaming the HTTP response.The current arrangement allows reading
InputStreamResource
withRestTemplate
, which should not be possible.Original report:
InputStreamResource are closed by SimpleClientHttpResponse
The http stream wrapped by InputStreamResource is closed by SimpleClientHttpResponse, rendering it unusable.
#1017 (comment)
I'll make a PR with a test.
Affects: 4.3.3
Reference URL: #18612
Issue Links:
Referenced from: commits afd93a0
The text was updated successfully, but these errors were encountered: