mirror of
https://github.com/spring-projects/spring-framework.git
synced 2026-09-17 16:39:29 +00:00
Simplify use of InputStream with RestClient
Closes gh-36380
This commit is contained in:
@@ -42,6 +42,7 @@ import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.io.InputStreamResource;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpRequest;
|
||||
@@ -253,6 +254,10 @@ final class DefaultRestClient implements RestClient {
|
||||
}
|
||||
}
|
||||
|
||||
if (bodyClass.equals(InputStream.class)) {
|
||||
return (T) responseWrapper.getBody();
|
||||
}
|
||||
|
||||
throw new UnknownContentTypeException(bodyType, contentType,
|
||||
responseWrapper.getStatusCode(), responseWrapper.getStatusText(),
|
||||
responseWrapper.getHeaders(), RestClientUtils.getBody(responseWrapper));
|
||||
@@ -609,7 +614,11 @@ final class DefaultRestClient implements RestClient {
|
||||
clientResponse = clientRequest.execute();
|
||||
observationContext.setResponse(clientResponse);
|
||||
ConvertibleClientHttpResponse convertibleWrapper = new DefaultConvertibleClientHttpResponse(clientResponse, this.hints);
|
||||
return exchangeFunction.exchange(clientRequest, convertibleWrapper);
|
||||
T result = exchangeFunction.exchange(clientRequest, convertibleWrapper);
|
||||
if (close && isStreamingResult(result)) {
|
||||
close = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
catch (IOException ex) {
|
||||
ResourceAccessException resourceAccessException = createResourceAccessException(uri, this.httpMethod, ex);
|
||||
@@ -746,6 +755,10 @@ final class DefaultRestClient implements RestClient {
|
||||
return request;
|
||||
}
|
||||
|
||||
private static boolean isStreamingResult(@Nullable Object result) {
|
||||
return (result instanceof InputStream || result instanceof InputStreamResource);
|
||||
}
|
||||
|
||||
private static ResourceAccessException createResourceAccessException(URI url, HttpMethod method, IOException ex) {
|
||||
StringBuilder msg = new StringBuilder("I/O error on ");
|
||||
msg.append(method.name());
|
||||
|
||||
+2
-29
@@ -16,8 +16,6 @@
|
||||
|
||||
package org.springframework.web.client.support;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -75,8 +73,7 @@ public final class RestClientAdapter implements HttpExchangeAdapter {
|
||||
|
||||
@Override
|
||||
public <T> @Nullable T exchangeForBody(HttpRequestValues values, ParameterizedTypeReference<T> bodyType) {
|
||||
return (bodyType.getType().equals(InputStream.class) ?
|
||||
exchangeForInputStream(values) : newRequest(values).retrieve().body(bodyType));
|
||||
return newRequest(values).retrieve().body(bodyType);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -86,21 +83,7 @@ public final class RestClientAdapter implements HttpExchangeAdapter {
|
||||
|
||||
@Override
|
||||
public <T> ResponseEntity<T> exchangeForEntity(HttpRequestValues values, ParameterizedTypeReference<T> bodyType) {
|
||||
return (bodyType.getType().equals(InputStream.class) ?
|
||||
exchangeForEntityInputStream(values) : newRequest(values).retrieve().toEntity(bodyType));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T exchangeForInputStream(HttpRequestValues values) {
|
||||
return (T) newRequest(values).exchange((request, response) -> getInputStream(response), false);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> ResponseEntity<T> exchangeForEntityInputStream(HttpRequestValues values) {
|
||||
return (ResponseEntity<T>) newRequest(values).exchangeForRequiredValue((request, response) ->
|
||||
ResponseEntity.status(response.getStatusCode())
|
||||
.headers(response.getHeaders())
|
||||
.body(getInputStream(response)), false);
|
||||
return newRequest(values).retrieve().toEntity(bodyType);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -162,16 +145,6 @@ public final class RestClientAdapter implements HttpExchangeAdapter {
|
||||
return bodySpec;
|
||||
}
|
||||
|
||||
private static InputStream getInputStream(
|
||||
RestClient.RequestHeadersSpec.ConvertibleClientHttpResponse response) throws IOException {
|
||||
|
||||
if (response.getStatusCode().isError()) {
|
||||
throw response.createException();
|
||||
}
|
||||
return response.getBody();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create a {@link RestClientAdapter} for the given {@link RestClient}.
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.web.client;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
@@ -36,6 +37,8 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* Tests for {@link DefaultRestClient}.
|
||||
@@ -117,6 +120,21 @@ class DefaultRestClientTests {
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
void inputStreamBody() throws IOException {
|
||||
mockSentRequest(HttpMethod.GET, "https://example.org");
|
||||
mockResponseStatus(HttpStatus.OK);
|
||||
mockResponseBody("Hello World", MediaType.TEXT_PLAIN);
|
||||
|
||||
InputStream result = this.client.get()
|
||||
.uri("https://example.org")
|
||||
.retrieve()
|
||||
.requiredBody(InputStream.class);
|
||||
|
||||
assertThat(result).isInstanceOf(InputStream.class);
|
||||
verify(this.response, times(0)).close();
|
||||
}
|
||||
|
||||
|
||||
private void mockSentRequest(HttpMethod method, String uri) throws IOException {
|
||||
given(this.requestFactory.createRequest(URI.create(uri), method)).willReturn(this.request);
|
||||
|
||||
Reference in New Issue
Block a user