Given the following:
@HttpServiceClient("example")
public interface ExampleClient {
@GetExchange("/{id}")
InputStream picture(@PathVariable int id);
}
I would expect calls to picture to throw an exception if HTTP 404 is returned. This is currently not the case (at least with RestClient backed interfaces.
I suspect this call will need to be updated so that the ExchangeFunction checks the status code.
Comment From: rstoyanchev
This is indeed a problem, but less clear how to fix it.
Status handling is applied under retrieve() but that calls the default exchange which ensures the response is closed. This is why RestClientAdapter calls exchange with close=false, but that leaves status handling to be duplicated.
ResourceHttpMessagerConverter supports InputStreamResource so technically we could use retrieve() but again that closes the response, and in fact going back to version 5.0 with #19448, the converter explicitly disables InputStreamResource support on the client side.
There is no easy way for RestClientAdapter to replicate the private, default status handling in RestClient. Using DefaultResponseErrorHandler is the closest, but that won't decode error response details, which requires access to message converters, and it won't apply default status handling configured via RestClient.Builder.
An alternative is to update DefaultRestClient to recognise response body types that imply the content will be consumed later, and call exchange with close=false. It would also require that ResourceHttpMessagerConverter is created with supportsReadStreaming set to true when used in RestClient (rather than RestTemplate). This might be a bit challenging also with the new HttpMessageConverters.ClientBuilder setting the flag to false by default.
One more option is to introduce a createException method on ConvertibleClientHttpResponse similar to the equivalent method on the WebClient response so that an exchange method can create an error exception.
Comment From: bclozel
Streaming the response body in RestTemplate has been a well requested feature, as we can see in linked issues for #19448.
I guess there are ways to use the HTTP response in a more flexible fashion with org.springframework.web.client.RestTemplate#doExecute and ResponseExtractor in general. The main problem is that we need to ensure that:
* the HTTP response is properly drained (otherwise the connection is in an invalid state and cannot return to the pool)
* the HTTP client observation is closed and timed the request/response exchange properly
* any IOException will result in the closing of the response
Leaking an InputStream from the HTTP response to the application can be challenging.
Comment From: rstoyanchev
The ability to return an InputStream from an HTTP service method is only a way to expose what is already possible with direct use of RestClient as shown in #32358, and further aided by the close flag on exchange.
That said, this is bringing up broader questions about the use of InputStream and streaming in RestClient, and we should consider first class support that takes into account concerns such as observability.
I've created #35391 for now to let us address this issue, and it is also independently useful. We can consider InputStream support at the RestClient level separately, and then update HTTP services accordingly.