Я использую RESTful JSON API, используя Spring RestTemplate
и Jackson. В некоторых случаях мы можем получить ответ Status 401
(неавторизованный) с настраиваемым телом JSON, который определен производителем API, и выглядит следующим образом:
{
"code": 123,
"message": "Reason for the error"
}
Нам нужно проанализировать тело и использовать свойство code
в нашей бизнес-логике.
Это Java-объект ответа на ошибку, который необходимо проанализировать:
public class CustomError {
@JsonProperty
private Integer code;
@JsonProperty
private String message;
public Integer getCode() {
return code;
}
public String getMessage() {
return message;
}
}
И пользовательский обработчик ошибок для этого:
public class CustomErrorHandler extends DefaultResponseErrorHandler {
private RestTemplate restTemplate;
private ObjectMapper objectMapper;
private MappingJacksonHttpMessageConverter messageConverter;
@Override
public boolean hasError(ClientHttpResponse response) throws IOException {
return super.hasError(response);
}
@Override
public void handleError(final ClientHttpResponse response) throws IOException {
try {
CustomError error =
(CustomError) messageConverter.read(CustomError.class, response);
throw new CustomErrorIOException(error, error.getMessage());
} catch (Exception e) {
// parsing failed, resort to default behavior
super.handleError(response);
}
}
}
Обработчик ошибок не работает с HttpMessageNotReadableException
в блоке try:
"Не удалось прочитать JSON: не удается выполнить повторную попытку из-за аутентификации сервера в режиме потоковой передачи"
Вот как я отправляю запросы:
restTemplate.postForObject(url, pojoInstance, responseClass);
Если один и тот же запрос выполняется с простой старой клиентской программой для отдыха, например Postman, ожидается ожидаемый ответ JSON. Таким образом, я предполагаю, что проблема может быть с реализацией Spring ClientHttpResponse
, так или иначе не позволяющей получить доступ к телу ответа в случае статуса 401.
Действительно ли можно проанализировать тело ответа?
Обновление
Из того, что я исследовал, класс RestTemplate
использует ClientHttpResponse
, который, в свою очередь, создает sun.net.www.protocol.http.HttpURLConnection
, который предоставляет входной поток. Он существует там, где игнорируется входной поток и бросается IOException
:
не может повторить попытку из-за аутентификации сервера, в потоковом режиме
Итак, реализация HttpURLConnection
вызывает проблему.
Можно ли избежать этой проблемы? Возможно, нам следует использовать альтернативную реализацию, которая не игнорирует тело ответа в случае кода состояния ошибки? Можете ли вы порекомендовать какие-либо альтернативы?