ResponseEntityExceptionHandler returns 401 异常的空响应正文

ResponseEntityExceptionHandler returns empty response body for 401 exceptions

我正在尝试使用 RestTemplate 实现对身份验证服务器的 Rest 调用,并记录响应以防服务器 returns 出现异常。为此,我使用了 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"
}

为什么您认为 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) { ... }

您需要预料到这种情况,并提供自定义响应正文。
实际的异常消息对 return 作为正文的一部分很有价值,它可能是一个复杂的对象。

我终于能够记录 401 异常的响应正文。我添加了依赖项

org.apache.httpcomponents:httpclient

并配置了 Rest 模板请求工厂

    restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory());

显然默认请求工厂 SimpleClientHttpRequestFactory 无法读取 401 Http 状态的响应正文。

我遇到了类似的 400 响应问题,并且上述使用 HttpComponentsClientHttpRequestFactory() 的解决方案无效。我可以通过使用 restTemplate.setFactory(new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory)); 来阅读正文。不确定是否有人遇到我同样的问题,但如果所选的解决方案不适合您,希望这会有所帮助。