Skip to content

Commit 21e6d73

Browse files
committed
Re-order methods and polishing
In StatusHandler and DefaultConvertibleClientHttpResponse. See gh-35391
1 parent a585bea commit 21e6d73

File tree

2 files changed

+104
-75
lines changed

2 files changed

+104
-75
lines changed

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

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -775,7 +775,7 @@ private class DefaultResponseSpec implements ResponseSpec {
775775
DefaultResponseSpec(RequestHeadersSpec<?> requestHeadersSpec) {
776776
this.requestHeadersSpec = requestHeadersSpec;
777777
this.statusHandlers.addAll(DefaultRestClient.this.defaultStatusHandlers);
778-
this.statusHandlers.add(StatusHandler.defaultHandler(DefaultRestClient.this.messageConverters));
778+
this.statusHandlers.add(StatusHandler.createDefaultStatusHandler(DefaultRestClient.this.messageConverters));
779779
this.defaultStatusHandlerCount = this.statusHandlers.size();
780780
}
781781

@@ -886,7 +886,10 @@ private Map<String, Object> getHints() {
886886
return this.requestHeadersSpec.exchange(exchangeFunction);
887887
}
888888

889-
private <T> @Nullable T readBody(HttpRequest request, ClientHttpResponse response, Type bodyType, Class<T> bodyClass, @Nullable Map<String, Object> hints) {
889+
private <T> @Nullable T readBody(
890+
HttpRequest request, ClientHttpResponse response, Type bodyType, Class<T> bodyClass,
891+
@Nullable Map<String, Object> hints) {
892+
890893
return DefaultRestClient.this.readWithMessageConverters(
891894
response, () -> applyStatusHandlers(request, response), bodyType, bodyClass, hints);
892895

@@ -923,40 +926,40 @@ public DefaultConvertibleClientHttpResponse(ClientHttpResponse delegate, @Nullab
923926
}
924927

925928
@Override
926-
public <T> @Nullable T bodyTo(Class<T> bodyType) {
927-
return readWithMessageConverters(this.delegate, () -> {} , bodyType, bodyType, this.hints);
929+
public HttpStatusCode getStatusCode() throws IOException {
930+
return this.delegate.getStatusCode();
928931
}
929932

930933
@Override
931-
public <T> @Nullable T bodyTo(ParameterizedTypeReference<T> bodyType) {
932-
Type type = bodyType.getType();
933-
Class<T> bodyClass = bodyClass(type);
934-
return readWithMessageConverters(this.delegate, () -> {}, type, bodyClass, this.hints);
934+
public String getStatusText() throws IOException {
935+
return this.delegate.getStatusText();
935936
}
936937

937938
@Override
938-
public InputStream getBody() throws IOException {
939-
return this.delegate.getBody();
939+
public HttpHeaders getHeaders() {
940+
return this.delegate.getHeaders();
940941
}
941942

942943
@Override
943-
public HttpHeaders getHeaders() {
944-
return this.delegate.getHeaders();
944+
public InputStream getBody() throws IOException {
945+
return this.delegate.getBody();
945946
}
946947

947948
@Override
948-
public HttpStatusCode getStatusCode() throws IOException {
949-
return this.delegate.getStatusCode();
949+
public void close() {
950+
this.delegate.close();
950951
}
951952

952953
@Override
953-
public String getStatusText() throws IOException {
954-
return this.delegate.getStatusText();
954+
public <T> @Nullable T bodyTo(Class<T> bodyType) {
955+
return readWithMessageConverters(this.delegate, () -> {} , bodyType, bodyType, this.hints);
955956
}
956957

957958
@Override
958-
public void close() {
959-
this.delegate.close();
959+
public <T> @Nullable T bodyTo(ParameterizedTypeReference<T> bodyType) {
960+
Type type = bodyType.getType();
961+
Class<T> bodyClass = bodyClass(type);
962+
return readWithMessageConverters(this.delegate, () -> {}, type, bodyClass, this.hints);
960963
}
961964
}
962965

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

Lines changed: 83 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -39,90 +39,103 @@
3939
import org.springframework.util.ObjectUtils;
4040

4141
/**
42-
* Used by {@link DefaultRestClient} and {@link DefaultRestClientBuilder}.
42+
* Simple container for an error response Predicate and an error response handler
43+
* to support the status handling mechanism of {@link RestClient.ResponseSpec}.
4344
*
4445
* @author Arjen Poutsma
46+
* @author Rossen Stoyanchev
4547
* @since 6.1
4648
*/
4749
final class StatusHandler {
4850

4951
private final ResponsePredicate predicate;
5052

51-
private final RestClient.ResponseSpec.ErrorHandler errorHandler;
53+
private final RestClient.ResponseSpec.ErrorHandler handler;
5254

5355

54-
private StatusHandler(ResponsePredicate predicate, RestClient.ResponseSpec.ErrorHandler errorHandler) {
56+
private StatusHandler(ResponsePredicate predicate, RestClient.ResponseSpec.ErrorHandler handler) {
5557
this.predicate = predicate;
56-
this.errorHandler = errorHandler;
58+
this.handler = handler;
5759
}
5860

5961

60-
public static StatusHandler of(Predicate<HttpStatusCode> predicate,
61-
RestClient.ResponseSpec.ErrorHandler errorHandler) {
62+
/**
63+
* Test whether the response has any errors.
64+
*/
65+
public boolean test(ClientHttpResponse response) throws IOException {
66+
return this.predicate.test(response);
67+
}
68+
69+
/**
70+
* Handle the error in the given response.
71+
* <p>This method is only called when {@link #test(ClientHttpResponse)}
72+
* has returned {@code true}.
73+
ß */
74+
public void handle(HttpRequest request, ClientHttpResponse response) throws IOException {
75+
this.handler.handle(request, response);
76+
}
77+
78+
79+
/**
80+
* Create a StatusHandler from a RestClient {@link RestClient.ResponseSpec.ErrorHandler}.
81+
*/
82+
public static StatusHandler of(
83+
Predicate<HttpStatusCode> predicate, RestClient.ResponseSpec.ErrorHandler errorHandler) {
84+
6285
Assert.notNull(predicate, "Predicate must not be null");
6386
Assert.notNull(errorHandler, "ErrorHandler must not be null");
6487

6588
return new StatusHandler(response -> predicate.test(response.getStatusCode()), errorHandler);
6689
}
6790

91+
/**
92+
* Create a StatusHandler from a {@link ResponseErrorHandler}.
93+
*/
6894
public static StatusHandler fromErrorHandler(ResponseErrorHandler errorHandler) {
6995
Assert.notNull(errorHandler, "ResponseErrorHandler must not be null");
7096

71-
return new StatusHandler(errorHandler::hasError, (request, response) ->
72-
errorHandler.handleError(request.getURI(), request.getMethod(), response));
97+
return new StatusHandler(errorHandler::hasError,
98+
(request, response) -> errorHandler.handleError(request.getURI(), request.getMethod(), response));
7399
}
74100

75-
public static StatusHandler defaultHandler(List<HttpMessageConverter<?>> messageConverters) {
101+
/**
102+
* Create a StatusHandler for default error response handling.
103+
*/
104+
public static StatusHandler createDefaultStatusHandler(List<HttpMessageConverter<?>> converters) {
76105
return new StatusHandler(response -> response.getStatusCode().isError(),
77106
(request, response) -> {
78-
HttpStatusCode statusCode = response.getStatusCode();
79-
String statusText = response.getStatusText();
80-
HttpHeaders headers = response.getHeaders();
81-
byte[] body = RestClientUtils.getBody(response);
82-
Charset charset = RestClientUtils.getCharset(response);
83-
String message = getErrorMessage(statusCode.value(), statusText, body, charset);
84-
RestClientResponseException ex;
85-
86-
if (statusCode.is4xxClientError()) {
87-
ex = HttpClientErrorException.create(message, statusCode, statusText, headers, body, charset);
88-
}
89-
else if (statusCode.is5xxServerError()) {
90-
ex = HttpServerErrorException.create(message, statusCode, statusText, headers, body, charset);
91-
}
92-
else {
93-
ex = new UnknownHttpStatusCodeException(message, statusCode.value(), statusText, headers, body, charset);
94-
}
95-
if (!CollectionUtils.isEmpty(messageConverters)) {
96-
ex.setBodyConvertFunction(initBodyConvertFunction(response, body, messageConverters));
97-
}
98-
throw ex;
107+
throw createException(response, converters);
99108
});
100109
}
101110

102-
@SuppressWarnings("NullAway")
103-
private static Function<ResolvableType, ? extends @Nullable Object> initBodyConvertFunction(ClientHttpResponse response, byte[] body, List<HttpMessageConverter<?>> messageConverters) {
104-
Assert.state(!CollectionUtils.isEmpty(messageConverters), "Expected message converters");
105-
return resolvableType -> {
106-
try {
107-
HttpMessageConverterExtractor<?> extractor =
108-
new HttpMessageConverterExtractor<>(resolvableType.getType(), messageConverters);
111+
private static RestClientResponseException createException(
112+
ClientHttpResponse response, List<HttpMessageConverter<?>> converters) throws IOException {
109113

110-
return extractor.extractData(new ClientHttpResponseDecorator(response) {
111-
@Override
112-
public InputStream getBody() {
113-
return new ByteArrayInputStream(body);
114-
}
115-
});
116-
}
117-
catch (IOException ex) {
118-
throw new RestClientException("Error while extracting response for type [" + resolvableType + "]", ex);
119-
}
120-
};
121-
}
114+
HttpStatusCode statusCode = response.getStatusCode();
115+
String statusText = response.getStatusText();
116+
HttpHeaders headers = response.getHeaders();
117+
byte[] body = RestClientUtils.getBody(response);
118+
Charset charset = RestClientUtils.getCharset(response);
119+
String message = getErrorMessage(statusCode.value(), statusText, body, charset);
120+
RestClientResponseException ex;
122121

122+
if (statusCode.is4xxClientError()) {
123+
ex = HttpClientErrorException.create(message, statusCode, statusText, headers, body, charset);
124+
}
125+
else if (statusCode.is5xxServerError()) {
126+
ex = HttpServerErrorException.create(message, statusCode, statusText, headers, body, charset);
127+
}
128+
else {
129+
ex = new UnknownHttpStatusCodeException(message, statusCode.value(), statusText, headers, body, charset);
130+
}
131+
if (!CollectionUtils.isEmpty(converters)) {
132+
ex.setBodyConvertFunction(initBodyConvertFunction(response, body, converters));
133+
}
134+
return ex;
135+
}
123136

124-
private static String getErrorMessage(int rawStatusCode, String statusText, byte @Nullable [] responseBody,
125-
@Nullable Charset charset) {
137+
private static String getErrorMessage(
138+
int rawStatusCode, String statusText, byte @Nullable [] responseBody, @Nullable Charset charset) {
126139

127140
String preface = rawStatusCode + " " + statusText + ": ";
128141

@@ -138,14 +151,27 @@ private static String getErrorMessage(int rawStatusCode, String statusText, byte
138151
return preface + bodyText;
139152
}
140153

154+
@SuppressWarnings("NullAway")
155+
private static Function<ResolvableType, ? extends @Nullable Object> initBodyConvertFunction(
156+
ClientHttpResponse response, byte[] body, List<HttpMessageConverter<?>> messageConverters) {
141157

158+
Assert.state(!CollectionUtils.isEmpty(messageConverters), "Expected message converters");
159+
return resolvableType -> {
160+
try {
161+
HttpMessageConverterExtractor<?> extractor =
162+
new HttpMessageConverterExtractor<>(resolvableType.getType(), messageConverters);
142163

143-
public boolean test(ClientHttpResponse response) throws IOException {
144-
return this.predicate.test(response);
145-
}
146-
147-
public void handle(HttpRequest request, ClientHttpResponse response) throws IOException {
148-
this.errorHandler.handle(request, response);
164+
return extractor.extractData(new ClientHttpResponseDecorator(response) {
165+
@Override
166+
public InputStream getBody() {
167+
return new ByteArrayInputStream(body);
168+
}
169+
});
170+
}
171+
catch (IOException ex) {
172+
throw new RestClientException("Error while extracting response for type [" + resolvableType + "]", ex);
173+
}
174+
};
149175
}
150176

151177

0 commit comments

Comments
 (0)