1616
1717package org .springframework .web .client ;
1818
19+ import java .io .ByteArrayInputStream ;
1920import java .io .IOException ;
21+ import java .io .InputStreamReader ;
22+ import java .io .Reader ;
23+ import java .nio .CharBuffer ;
2024import java .nio .charset .Charset ;
25+ import java .nio .charset .StandardCharsets ;
2126
2227import org .springframework .http .HttpHeaders ;
2328import org .springframework .http .HttpStatus ;
2429import org .springframework .http .MediaType ;
2530import org .springframework .http .client .ClientHttpResponse ;
2631import org .springframework .lang .Nullable ;
2732import org .springframework .util .FileCopyUtils ;
33+ import org .springframework .util .ObjectUtils ;
2834
2935/**
3036 * Spring's default implementation of the {@link ResponseErrorHandler} interface.
@@ -96,12 +102,51 @@ protected boolean hasError(int unknownStatusCode) {
96102 public void handleError (ClientHttpResponse response ) throws IOException {
97103 HttpStatus statusCode = HttpStatus .resolve (response .getRawStatusCode ());
98104 if (statusCode == null ) {
99- throw new UnknownHttpStatusCodeException (response .getRawStatusCode (), response .getStatusText (),
105+ String message = getErrorMessage (
106+ response .getRawStatusCode (), response .getStatusText (),
107+ getResponseBody (response ), getCharset (response ));
108+ throw new UnknownHttpStatusCodeException (message ,
109+ response .getRawStatusCode (), response .getStatusText (),
100110 response .getHeaders (), getResponseBody (response ), getCharset (response ));
101111 }
102112 handleError (response , statusCode );
103113 }
104114
115+ /**
116+ * Return error message with details from the response body, possibly truncated:
117+ * <pre>
118+ * 404 Not Found: [{'id': 123, 'message': 'my very long... (500 bytes)]
119+ * </pre>
120+ */
121+ private String getErrorMessage (
122+ int rawStatusCode , String statusText , @ Nullable byte [] responseBody , @ Nullable Charset charset ) {
123+
124+ String preface = rawStatusCode + " " + statusText + ": " ;
125+ if (ObjectUtils .isEmpty (responseBody )) {
126+ return preface + "[no body]" ;
127+ }
128+
129+ charset = charset == null ? StandardCharsets .UTF_8 : charset ;
130+ int maxChars = 200 ;
131+
132+ if (responseBody .length < maxChars * 2 ) {
133+ return preface + "[" + new String (responseBody , charset ) + "]" ;
134+ }
135+
136+ try {
137+ Reader reader = new InputStreamReader (new ByteArrayInputStream (responseBody ), charset );
138+ CharBuffer buffer = CharBuffer .allocate (maxChars );
139+ reader .read (buffer );
140+ reader .close ();
141+ buffer .flip ();
142+ return preface + "[" + buffer .toString () + "... (" + responseBody .length + " bytes)]" ;
143+ }
144+ catch (IOException ex ) {
145+ // should never happen
146+ throw new IllegalStateException (ex );
147+ }
148+ }
149+
105150 /**
106151 * Handle the error in the given response with the given resolved status code.
107152 * <p>The default implementation throws an {@link HttpClientErrorException}
@@ -118,13 +163,15 @@ protected void handleError(ClientHttpResponse response, HttpStatus statusCode) t
118163 HttpHeaders headers = response .getHeaders ();
119164 byte [] body = getResponseBody (response );
120165 Charset charset = getCharset (response );
166+ String message = getErrorMessage (statusCode .value (), statusText , body , charset );
167+
121168 switch (statusCode .series ()) {
122169 case CLIENT_ERROR :
123- throw HttpClientErrorException .create (statusCode , statusText , headers , body , charset );
170+ throw HttpClientErrorException .create (message , statusCode , statusText , headers , body , charset );
124171 case SERVER_ERROR :
125- throw HttpServerErrorException .create (statusCode , statusText , headers , body , charset );
172+ throw HttpServerErrorException .create (message , statusCode , statusText , headers , body , charset );
126173 default :
127- throw new UnknownHttpStatusCodeException (statusCode .value (), statusText , headers , body , charset );
174+ throw new UnknownHttpStatusCodeException (message , statusCode .value (), statusText , headers , body , charset );
128175 }
129176 }
130177
0 commit comments