Skip to content

Commit 441b14b

Browse files
committed
Handle error responses in RestClientAdapter
Closes gh-35375
1 parent f22d1ea commit 441b14b

File tree

2 files changed

+39
-13
lines changed

2 files changed

+39
-13
lines changed

spring-web/src/main/java/org/springframework/web/client/support/RestClientAdapter.java

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package org.springframework.web.client.support;
1818

19+
import java.io.IOException;
1920
import java.io.InputStream;
2021
import java.net.URI;
2122
import java.util.ArrayList;
@@ -72,30 +73,34 @@ public HttpHeaders exchangeForHeaders(HttpRequestValues values) {
7273
return newRequest(values).retrieve().toBodilessEntity().getHeaders();
7374
}
7475

75-
@SuppressWarnings("unchecked")
7676
@Override
7777
public <T> @Nullable T exchangeForBody(HttpRequestValues values, ParameterizedTypeReference<T> bodyType) {
78-
if (bodyType.getType().equals(InputStream.class)) {
79-
return (T) newRequest(values).exchange((request, response) -> response.getBody(), false);
80-
}
81-
return newRequest(values).retrieve().body(bodyType);
78+
return (bodyType.getType().equals(InputStream.class) ?
79+
exchangeForInputStream(values) : newRequest(values).retrieve().body(bodyType));
8280
}
8381

8482
@Override
8583
public ResponseEntity<Void> exchangeForBodilessEntity(HttpRequestValues values) {
8684
return newRequest(values).retrieve().toBodilessEntity();
8785
}
8886

89-
@SuppressWarnings("unchecked")
9087
@Override
9188
public <T> ResponseEntity<T> exchangeForEntity(HttpRequestValues values, ParameterizedTypeReference<T> bodyType) {
92-
if (bodyType.getType().equals(InputStream.class)) {
93-
return (ResponseEntity<T>) newRequest(values).exchangeForRequiredValue((request, response) ->
94-
ResponseEntity.status(response.getStatusCode())
95-
.headers(response.getHeaders())
96-
.body(response.getBody()), false);
97-
}
98-
return newRequest(values).retrieve().toEntity(bodyType);
89+
return (bodyType.getType().equals(InputStream.class) ?
90+
exchangeForEntityInputStream(values) : newRequest(values).retrieve().toEntity(bodyType));
91+
}
92+
93+
@SuppressWarnings("unchecked")
94+
private <T> T exchangeForInputStream(HttpRequestValues values) {
95+
return (T) newRequest(values).exchange((request, response) -> getInputStream(response), false);
96+
}
97+
98+
@SuppressWarnings("unchecked")
99+
private <T> ResponseEntity<T> exchangeForEntityInputStream(HttpRequestValues values) {
100+
return (ResponseEntity<T>) newRequest(values).exchangeForRequiredValue((request, response) ->
101+
ResponseEntity.status(response.getStatusCode())
102+
.headers(response.getHeaders())
103+
.body(getInputStream(response)), false);
99104
}
100105

101106
@SuppressWarnings("unchecked")
@@ -157,6 +162,16 @@ else if (values.getBodyValueType() != null) {
157162
return bodySpec;
158163
}
159164

165+
private static InputStream getInputStream(
166+
RestClient.RequestHeadersSpec.ConvertibleClientHttpResponse response) throws IOException {
167+
168+
if (response.getStatusCode().isError()) {
169+
throw response.createException();
170+
}
171+
return response.getBody();
172+
}
173+
174+
160175

161176
/**
162177
* Create a {@link RestClientAdapter} for the given {@link RestClient}.

spring-web/src/test/java/org/springframework/web/client/support/RestClientAdapterTests.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
import org.springframework.web.bind.annotation.RequestParam;
5757
import org.springframework.web.bind.annotation.RequestPart;
5858
import org.springframework.web.client.ApiVersionInserter;
59+
import org.springframework.web.client.HttpClientErrorException;
5960
import org.springframework.web.client.RestClient;
6061
import org.springframework.web.client.RestTemplate;
6162
import org.springframework.web.multipart.MultipartFile;
@@ -69,6 +70,7 @@
6970
import org.springframework.web.util.UriBuilderFactory;
7071

7172
import static org.assertj.core.api.Assertions.assertThat;
73+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
7274

7375
/**
7476
* Integration tests for {@link HttpServiceProxyFactory} with {@link RestClient}
@@ -335,6 +337,15 @@ void getInputStream() throws Exception {
335337
assertThat(StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8)).isEqualTo("Hello Spring 2!");
336338
}
337339

340+
@Test // gh-35375
341+
void getInputStreamWithError() {
342+
prepareResponse(builder -> builder.code(400).body("rejected"));
343+
344+
assertThatThrownBy(() -> initService().getInputStream())
345+
.isExactlyInstanceOf(HttpClientErrorException.BadRequest.class)
346+
.hasMessage("400 Client Error: \"rejected\"");
347+
}
348+
338349
@Test
339350
void postOutputStream() throws Exception {
340351
prepareResponse(builder ->

0 commit comments

Comments
 (0)