java.net.HttpRetryException:在流模式下无法由于服务器身份验证而重试

Ole*_*_DJ 26 java servlets http

我们的应用程序中有两个部分:
服务器 - 提供REST服务
客户端 - 通过Spring restTemplate使用它们

除了HTTP状态之外,我们的服务器还返回一个带有JSON的HTTP主体,它详细描述了错误.所以,我已经为restTemplate添加了自定义错误处理程序来处理一些编码为非错误的错误 - 它有助于解析HTTP正文.

但是,在HTTP/1.1 401 Unauthorized的情况下,我通过解析HTTP正文获得异常.所有其他错误代码都处理得很好(400,402等)我们正在使用普通服务器逻辑,在发生错误时发送HTTP响应,对于不同类型的错误没有特殊规则:

writeErrorToResponse(int status, String errMsg, HttpServletResponse resp) throws IOException {
        response.setStatus(status);
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        String message = String.format("{\"error\":\"%s\"}", StringUtils.escapeJson(errMsg));
        resp.getWriter().println(message);
    }
Run Code Online (Sandbox Code Playgroud)

但在客户端只有HTTP/1.1 401抛出异常 - "java.net.HttpRetryException: cannot retry due to server authentication, in streaming mode"

我做了一些调试,发现问题的原因是SimpleClientHttpResponse中的代码:

HttpURLConnection.getInputStream()

使用Fiddler进行跟踪会有以下响应:在客户端上解析消息是正确的:

HTTP/1.1 402 Payment Required
X-Powered-By: Servlet/3.0
Content-Type: application/json
Content-Language: en-GB
Content-Length: 55
Connection: Close
Date: Sat, 25 May 2013 10:10:44 GMT
Server: WebSphere Application Server/8.0

{"error":"I cant find that user.  Please try again."}
Run Code Online (Sandbox Code Playgroud)

并且是导致异常的消息:

HTTP/1.1 401 Unauthorized
X-Powered-By: Servlet/3.0
Content-Type: application/json
Content-Language: en-GB
Content-Length: 55
Date: Sat, 25 May 2013 11:00:21 GMT
Server: WebSphere Application Server/8.0

{"error":"I cant find that user.  Please try again."}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,java.net.HttpRetryException可能是什么原因?

另外:很久以前这种机制运行良好.但是因为我们在应用程序中更改了很多代码.

Har*_*han 25

使用SimpleClientHttpRequestFactory时遇到了同样的问题.通过设置解决了它

SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setOutputStreaming(false);
return requestFactory;
Run Code Online (Sandbox Code Playgroud)

问题是由于分块和随后的重试机制导致的身份验证.

您还可以使用HttpClientPolicy禁用块


You*_*ess 9

我认为将配置好的HttpComponentsClientHttpRequestFactory传递给RestTemplate会有所帮助. 在这里,您可以找到有关如何执行此操作的解决方案.

我使用这种开发解决方案的原因是处理Http错误响应(如401,404等)中的响应消息,并且还让应用程序部署在真实服务器端环境中.


Jim*_*Cox 8

我在使用 Spring Boot 2.2.4 和 TestRestTemplate 时遇到了完全相同的问题。它仅在 401 上失败。只需在测试范围内添加最新版本的Http Client (4.5.11) 即可解决问题。无需进一步配置。


Hem*_*nth 6

在Spring Framework中报告了此问题。

参考https : //jira.spring.io/browse/SPR-9367

从引用中复制: 使用默认设置很难(不可能)在RestTemplate中处理401响应。实际上是可行的,但是您必须提供错误处理程序和请求工厂。错误处理程序是显而易见的,但是问题是默认的请求工厂使用java.net,当您尝试查看响应的状态代码时,它可能引发HttpRetryException(尽管它显然是可用的)。解决方案是使用HttpComponentsClientHttpRequestFactory。例如

template.setRequestFactory(new HttpComponentsClientHttpRequestFactory());
template.setErrorHandler(new DefaultResponseErrorHandler() {
    public boolean hasError(ClientHttpResponse response) throws IOException {
        HttpStatus statusCode = response.getStatusCode();
        return statusCode.series() == HttpStatus.Series.SERVER_ERROR;
    }
});
Run Code Online (Sandbox Code Playgroud)

HttpComponentsClientHttpRequestFactory需要以下依赖关系。在您的POM文件中添加以下依赖项:

<dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
</dependency>
Run Code Online (Sandbox Code Playgroud)

  • 救生员,不知道如何自己解决这个问题? (3认同)