Я пытаюсь реализовать вызов Rest на сервер аутентификации с помощью RestTemplate и зарегистрировать ответ на случай, если сервер вернет исключение. Для этого я использовал ResponseEntityExceptionHandler для обработки исключений HttpClientErrorException и HttpServerErrorException.
public Response sendRequest(Request requestBody, String url, HttpMethod httpMethod, Response responseBody) {
RestTemplate restTemplate = new RestTemplate();
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(requestBody.getBody(),
this.securityHeaders);
ResponseEntity<? extends Response> response = restTemplate.exchange(url, httpMethod, request,
responseBody.getClass());
return response.getBody();
}
В настоящее время мой ResponseEntityExceptionHandler выглядит следующим образом
@ControllerAdvice
public class RestResponseExceptionHandler extends ResponseEntityExceptionHandler {
private static Logger log = LoggerFactory.getLogger(RestResponseExceptionHandler.class);
private HttpHeaders headers = new HttpHeaders();
@ExceptionHandler(value = { HttpClientErrorException.class, HttpServerErrorException.class })
protected ResponseEntity<Object> handleConflict(HttpStatusCodeException ex, WebRequest request) {
ErrorMessage responseBody = new ErrorMessage();
try {
JSONObject bodyOfException = new JSONObject(ex.getResponseBodyAsString());
log.warn("{}| {}", ex.getStatusCode(), bodyOfException);
responseBody.setErrorAndDescription(bodyOfException.optString("error"),
bodyOfException.optString("error_description"));
} catch (JSONException e) {
log.error("{}| Bad authentication response body | Response Body | {}", ex.getStatusCode(),
ex.getResponseBodyAsString());
}
return handleExceptionInternal(ex, responseBody, headers, ex.getStatusCode(), request);
}
}
Однако только для исключений HttpStatus 401 я получаю пустой текст ответа.
Пример журналов:
400| {"error_description":"Bad client credentials","error":"invalid_client"}
401| Bad authentication response body | Response Body |
Кто-нибудь знает, как я могу получить тело ответа для исключений 401?
Редактировать: При использовании почтальона для вызова сервера аутентификации я получаю ненулевой 401 responseBody:
{
"error": "invalid_token",
"error_description": "Token was not recognised"
}
Да, это журналы для 2 разных запросов, один с ответом 401, а другой с ответом 400.




Как вы думаете, почему у HttpStatusCodeExceptionдолжен есть тело ответа? Это не так.
Посмотрите на конструктор RestClientResponseException, его прямого суперкласса.
...
* @param responseBody the response body content (may be {@code null})
* @param responseCharset the response body charset (may be {@code null})
*/
public RestClientResponseException(
String message,
int statusCode,
String statusText,
@Nullable HttpHeaders responseHeaders,
@Nullable byte[] responseBody,
@Nullable Charset responseCharset) { ... }
Вам нужно ожидать этого случая и предоставить собственное тело ответа.
Фактическое сообщение об исключении является хорошим значением для возврата как части тела, которое может быть сложным объектом.
Да, я знаю, что responseBody может быть Null. Однако, когда я использую Postman для вызова сервера аутентификации, и я получаю ненулевой ответBody
@TheStiff, не могли бы вы опубликовать ответ, который вы получили на звонок почтальона?
Да, я добавил это в исходный пост
@TheStiff Найдите DefaultResponseErrorHandler#handleError. Поставьте там точку останова и посмотрите на строку "byte[] body = getResponseBody(response);"
Спасибо, я сделал, как вы сказали, и заметил, что для ответов 401 метод getResponseBody выдавал исключение. Что привело меня к правильному пути вокруг этого. Я разместил решение в качестве ответа в этом сообщении.
Наконец-то я смог зарегистрировать тело ответа для исключения 401. Я добавил зависимость
org.apache.httpcomponents:httpclient
и настроена фабрика запросов шаблонов отдыха
restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory());
По-видимому, фабрика запросов по умолчанию SimpleClientHttpRequestFactory не может прочитать тело ответа для статуса 401 Http.
Спасибо за ответ, тоже мучаюсь с этой проблемой. Ваше здоровье!
Просто дополнительная помощь. Рассматриваемый класс - docs.spring.io/spring-framework/docs/current/javadoc-api/org/….
У меня была аналогичная проблема с ответом 400, и приведенное выше решение с использованием HttpComponentsClientHttpRequestFactory() не сработало. Вместо этого я смог прочитать тело, используя restTemplate.setFactory(new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory));. Не уверен, что у кого-то есть такая же проблема, но, надеюсь, это поможет, если выбранное решение не работает для вас.
ваш журнал имеет два разных кода состояния 400 и 401