获取 java.net.HttpRetryException:由于服务器身份验证,无法在流模式下重试
Getting java.net.HttpRetryException: cannot retry due to server authentication, in streaming mode
我已经为创建新用户创建了一个测试:
private static String USERS_ENDPOINT = "http://localhost:8080/users/";
private static String GROUPS_ENDPOINT = "http://localhost:8080/groups/";
@Test
@DirtiesContext(classMode = ClassMode.BEFORE_EACH_TEST_METHOD)
public void whenCreateAppUser() {
AppUser appUser = new AppUser();
appUser.setUsername("test@example.com");
appUser.setPassword("password");
// Throws java.net.HttpRetryException
template.postForEntity(USERS_ENDPOINT, appUser, AppUser.class);
ResponseEntity<AppUser> appUserResponse = template.getForEntity(USERS_ENDPOINT + "1/", AppUser.class);
assertEquals("Username is incorrect. AppUser not created?",
appUser.getUsername(), appUserResponse.getBody().getUsername());
}
但是,出于某种原因我得到:
Caused by: java.net.HttpRetryException: cannot retry due to server authentication, in streaming mode
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1692)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1492)
at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480)
at org.springframework.http.client.SimpleClientHttpResponse.getRawStatusCode(SimpleClientHttpResponse.java:55)
at org.springframework.web.client.DefaultResponseErrorHandler.hasError(DefaultResponseErrorHandler.java:49)
at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:735)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:700)
... 34 more
来电
template.postForEntity(USERS_ENDPOINT, appUser, AppUser.class);
我实际上不知道我改变了什么,因为这曾经对我有用。知道是什么导致了这个问题吗?
我的 WebSecurity
设置是:
@Override
public void configure(WebSecurity web) throws Exception {
final String[] SWAGGER_UI = {
"/swagger-resources/**",
"/swagger-ui.html",
"/v2/api-docs",
"/webjars/**"
};
web.ignoring().antMatchers("/pub/**", "/users")
.antMatchers(SWAGGER_UI);
}
Spring 的 RestTemplate
和 Spring Boot 的 TestRestTemplate
默认情况下将在 JDK 的内部 HttpURLConnection
实现上,无法访问状态为 401 "Unauthorized".
的 HTTP 响应的 body
一个神奇的解决方案是将 Apache 的 HTTP 客户端包含到类路径中 — 例如使用 Maven:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.6</version>
<scope>test</scope>
</dependency>
在这种情况下,Spring(或 Spring 引导)将使用 Apache 的 HTTP 客户端,不会遇到问题。
另请参阅:https://github.com/spring-projects/spring-security-oauth/issues/441#issuecomment-92033542
P.S。我刚刚遇到了同样的问题:)
使用 Apache HttpComponents Client 库中的 HttpClient 解决了我的问题。
要使用 Apache HttpClient,您必须按以下方式配置 RestTemplate:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RestClientConfig {
@Bean
public RestTemplate restTemplate() {
var template = new RestTemplate();
template.setRequestFactory(new HttpComponentsClientHttpRequestFactory());
return template;
}
}
如
中的回答
另一种选择是:
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setOutputStreaming(false);
return requestFactory;
我已经为创建新用户创建了一个测试:
private static String USERS_ENDPOINT = "http://localhost:8080/users/";
private static String GROUPS_ENDPOINT = "http://localhost:8080/groups/";
@Test
@DirtiesContext(classMode = ClassMode.BEFORE_EACH_TEST_METHOD)
public void whenCreateAppUser() {
AppUser appUser = new AppUser();
appUser.setUsername("test@example.com");
appUser.setPassword("password");
// Throws java.net.HttpRetryException
template.postForEntity(USERS_ENDPOINT, appUser, AppUser.class);
ResponseEntity<AppUser> appUserResponse = template.getForEntity(USERS_ENDPOINT + "1/", AppUser.class);
assertEquals("Username is incorrect. AppUser not created?",
appUser.getUsername(), appUserResponse.getBody().getUsername());
}
但是,出于某种原因我得到:
Caused by: java.net.HttpRetryException: cannot retry due to server authentication, in streaming mode
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1692)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1492)
at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480)
at org.springframework.http.client.SimpleClientHttpResponse.getRawStatusCode(SimpleClientHttpResponse.java:55)
at org.springframework.web.client.DefaultResponseErrorHandler.hasError(DefaultResponseErrorHandler.java:49)
at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:735)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:700)
... 34 more
来电
template.postForEntity(USERS_ENDPOINT, appUser, AppUser.class);
我实际上不知道我改变了什么,因为这曾经对我有用。知道是什么导致了这个问题吗?
我的 WebSecurity
设置是:
@Override
public void configure(WebSecurity web) throws Exception {
final String[] SWAGGER_UI = {
"/swagger-resources/**",
"/swagger-ui.html",
"/v2/api-docs",
"/webjars/**"
};
web.ignoring().antMatchers("/pub/**", "/users")
.antMatchers(SWAGGER_UI);
}
Spring 的 RestTemplate
和 Spring Boot 的 TestRestTemplate
默认情况下将在 JDK 的内部 HttpURLConnection
实现上,无法访问状态为 401 "Unauthorized".
一个神奇的解决方案是将 Apache 的 HTTP 客户端包含到类路径中 — 例如使用 Maven:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.6</version>
<scope>test</scope>
</dependency>
在这种情况下,Spring(或 Spring 引导)将使用 Apache 的 HTTP 客户端,不会遇到问题。
另请参阅:https://github.com/spring-projects/spring-security-oauth/issues/441#issuecomment-92033542
P.S。我刚刚遇到了同样的问题:)
使用 Apache HttpComponents Client 库中的 HttpClient 解决了我的问题。
要使用 Apache HttpClient,您必须按以下方式配置 RestTemplate:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RestClientConfig {
@Bean
public RestTemplate restTemplate() {
var template = new RestTemplate();
template.setRequestFactory(new HttpComponentsClientHttpRequestFactory());
return template;
}
}
如
中的回答另一种选择是:
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setOutputStreaming(false);
return requestFactory;