Browse Source

Handle error responses in RestClientAdapter

Closes gh-35375
pull/35397/head
rstoyanchev 7 months ago
parent
commit
441b14b0c1
  1. 41
      spring-web/src/main/java/org/springframework/web/client/support/RestClientAdapter.java
  2. 11
      spring-web/src/test/java/org/springframework/web/client/support/RestClientAdapterTests.java

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

@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
package org.springframework.web.client.support;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.ArrayList;
@ -72,13 +73,10 @@ public final class RestClientAdapter implements HttpExchangeAdapter { @@ -72,13 +73,10 @@ public final class RestClientAdapter implements HttpExchangeAdapter {
return newRequest(values).retrieve().toBodilessEntity().getHeaders();
}
@SuppressWarnings("unchecked")
@Override
public <T> @Nullable T exchangeForBody(HttpRequestValues values, ParameterizedTypeReference<T> bodyType) {
if (bodyType.getType().equals(InputStream.class)) {
return (T) newRequest(values).exchange((request, response) -> response.getBody(), false);
}
return newRequest(values).retrieve().body(bodyType);
return (bodyType.getType().equals(InputStream.class) ?
exchangeForInputStream(values) : newRequest(values).retrieve().body(bodyType));
}
@Override
@ -86,16 +84,23 @@ public final class RestClientAdapter implements HttpExchangeAdapter { @@ -86,16 +84,23 @@ public final class RestClientAdapter implements HttpExchangeAdapter {
return newRequest(values).retrieve().toBodilessEntity();
}
@SuppressWarnings("unchecked")
@Override
public <T> ResponseEntity<T> exchangeForEntity(HttpRequestValues values, ParameterizedTypeReference<T> bodyType) {
if (bodyType.getType().equals(InputStream.class)) {
return (ResponseEntity<T>) newRequest(values).exchangeForRequiredValue((request, response) ->
ResponseEntity.status(response.getStatusCode())
.headers(response.getHeaders())
.body(response.getBody()), false);
}
return newRequest(values).retrieve().toEntity(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);
}
@SuppressWarnings("unchecked")
@ -157,6 +162,16 @@ public final class RestClientAdapter implements HttpExchangeAdapter { @@ -157,6 +162,16 @@ 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}.

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

@ -56,6 +56,7 @@ import org.springframework.web.bind.annotation.RequestHeader; @@ -56,6 +56,7 @@ import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.client.ApiVersionInserter;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestClient;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
@ -69,6 +70,7 @@ import org.springframework.web.util.DefaultUriBuilderFactory; @@ -69,6 +70,7 @@ import org.springframework.web.util.DefaultUriBuilderFactory;
import org.springframework.web.util.UriBuilderFactory;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
/**
* Integration tests for {@link HttpServiceProxyFactory} with {@link RestClient}
@ -335,6 +337,15 @@ class RestClientAdapterTests { @@ -335,6 +337,15 @@ class RestClientAdapterTests {
assertThat(StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8)).isEqualTo("Hello Spring 2!");
}
@Test // gh-35375
void getInputStreamWithError() {
prepareResponse(builder -> builder.code(400).body("rejected"));
assertThatThrownBy(() -> initService().getInputStream())
.isExactlyInstanceOf(HttpClientErrorException.BadRequest.class)
.hasMessage("400 Client Error: \"rejected\"");
}
@Test
void postOutputStream() throws Exception {
prepareResponse(builder ->

Loading…
Cancel
Save