Skip to content

Commit d204dd2

Browse files
committed
Use IntrospectingClientHttpResponse in RestClient
This commit ensures that the RestClient uses the IntrospectingClientHttpResponse to verify whether the response has a body, and return null if it does not. See gh-12671 Closes gh-31719
1 parent 0dbb0f5 commit d204dd2

File tree

2 files changed

+33
-5
lines changed

2 files changed

+33
-5
lines changed

spring-web/src/main/java/org/springframework/web/client/DefaultRestClient.java

+16-5
Original file line numberDiff line numberDiff line change
@@ -184,32 +184,40 @@ public Builder mutate() {
184184
return new DefaultRestClientBuilder(this.builder);
185185
}
186186

187+
@Nullable
187188
@SuppressWarnings({"rawtypes", "unchecked"})
188-
private <T> T readWithMessageConverters(ClientHttpResponse clientResponse, Runnable callback, Type bodyType, Class<T> bodyClass) {
189+
private <T> T readWithMessageConverters(ClientHttpResponse clientResponse, Runnable callback, Type bodyType,
190+
Class<T> bodyClass) {
191+
189192
MediaType contentType = getContentType(clientResponse);
190193

191194
try (clientResponse) {
192195
callback.run();
193196

197+
IntrospectingClientHttpResponse responseWrapper = new IntrospectingClientHttpResponse(clientResponse);
198+
if (!responseWrapper.hasMessageBody() || responseWrapper.hasEmptyMessageBody()) {
199+
return null;
200+
}
201+
194202
for (HttpMessageConverter<?> messageConverter : this.messageConverters) {
195203
if (messageConverter instanceof GenericHttpMessageConverter genericHttpMessageConverter) {
196204
if (genericHttpMessageConverter.canRead(bodyType, null, contentType)) {
197205
if (logger.isDebugEnabled()) {
198206
logger.debug("Reading to [" + ResolvableType.forType(bodyType) + "]");
199207
}
200-
return (T) genericHttpMessageConverter.read(bodyType, null, clientResponse);
208+
return (T) genericHttpMessageConverter.read(bodyType, null, responseWrapper);
201209
}
202210
}
203211
if (messageConverter.canRead(bodyClass, contentType)) {
204212
if (logger.isDebugEnabled()) {
205213
logger.debug("Reading to [" + bodyClass.getName() + "] as \"" + contentType + "\"");
206214
}
207-
return (T) messageConverter.read((Class)bodyClass, clientResponse);
215+
return (T) messageConverter.read((Class)bodyClass, responseWrapper);
208216
}
209217
}
210218
throw new UnknownContentTypeException(bodyType, contentType,
211-
clientResponse.getStatusCode(), clientResponse.getStatusText(),
212-
clientResponse.getHeaders(), RestClientUtils.getBody(clientResponse));
219+
responseWrapper.getStatusCode(), responseWrapper.getStatusText(),
220+
responseWrapper.getHeaders(), RestClientUtils.getBody(responseWrapper));
213221
}
214222
catch (UncheckedIOException | IOException | HttpMessageNotReadableException ex) {
215223
throw new RestClientException("Error while extracting response for type [" +
@@ -585,11 +593,13 @@ private ResponseSpec onStatusInternal(StatusHandler statusHandler) {
585593
}
586594

587595
@Override
596+
@Nullable
588597
public <T> T body(Class<T> bodyType) {
589598
return readBody(bodyType, bodyType);
590599
}
591600

592601
@Override
602+
@Nullable
593603
public <T> T body(ParameterizedTypeReference<T> bodyType) {
594604
Type type = bodyType.getType();
595605
Class<T> bodyClass = bodyClass(type);
@@ -637,6 +647,7 @@ public ResponseEntity<Void> toBodilessEntity() {
637647
}
638648

639649

650+
@Nullable
640651
private <T> T readBody(Type bodyType, Class<T> bodyClass) {
641652
return DefaultRestClient.this.readWithMessageConverters(this.clientResponse, this::applyStatusHandlers,
642653
bodyType, bodyClass);

spring-web/src/test/java/org/springframework/web/client/RestClientIntegrationTests.java

+17
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,23 @@ void retrieveJsonNull(ClientHttpRequestFactory requestFactory) {
348348
assertThat(result).isNull();
349349
}
350350

351+
@ParameterizedRestClientTest
352+
@SuppressWarnings({ "rawtypes", "unchecked" })
353+
void retrieveJsonEmpty(ClientHttpRequestFactory requestFactory) {
354+
startServer(requestFactory);
355+
356+
prepareResponse(response -> response
357+
.setResponseCode(200)
358+
.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE));
359+
360+
Pojo result = this.restClient.get()
361+
.uri("/null")
362+
.retrieve()
363+
.body(Pojo.class);
364+
365+
assertThat(result).isNull();
366+
}
367+
351368
@ParameterizedRestClientTest
352369
void retrieve404(ClientHttpRequestFactory requestFactory) {
353370
startServer(requestFactory);

0 commit comments

Comments
 (0)