java code
public static void main(String[] args) {
String content = "xxxxx";
String accessToken = "75_0jAs7cd0fjJJFvYMaIdY4P9RqMdHYpCGnFGItX0RFT_i1HGDl7GMCoN3eyvkCKBCjp4uJHFKBNfrW-gulrAmllT7hH58yysL1LyyFll4E8MSJbk6BWp-41AujnEKLFdAIABCW";
String xin = "ofvdc5su2aEAuf4zjKC5A1tmCgrw";
Arrays.asList(xin).forEach(user -> {
Map<String, Object> request = new HashMap<>();
request.put("touser", user);
request.put("template_id", "fFNqKSC1M6y2k_iG-Koytbyk4kTaLJK3LiCn4cGkehQ");
request.put("url", "https://wechat.gyfyy.com/gy1yqlc/user/h5/index.html");
request.put("client_msg_id", System.currentTimeMillis() / 1000 + "");
request.put("data", new HashMap<String, Object>() {{
put("content", new HashMap<String, String>() {{
put("value", content);
put("color", "#173177");
}});
}});
String s = Runner.restTemplate.postForObject("https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + accessToken,
new HttpEntity<>(request, new LinkedMultiValueMap<String, String>() {{
add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
}}), String.class);
System.out.println("s = " + s);
});
}
spring-web:6.1.1
Send a request. Result is:
Exception in thread "main" org.springframework.web.client.HttpClientErrorException: 412 Precondition Failed: [no body]
at org.springframework.web.client.HttpClientErrorException.create(HttpClientErrorException.java:136)
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:183)
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:137)
at org.springframework.web.client.ResponseErrorHandler.handleError(ResponseErrorHandler.java:63)
at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:932)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:881)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:781)
at org.springframework.web.client.RestTemplate.postForObject(RestTemplate.java:498)
at org.exam.Runner.lambda$main$1(Runner.java:144)
at java.base/java.util.Arrays$ArrayList.forEach(Arrays.java:4204)
at org.exam.Runner.main(Runner.java:132)
Disconnected from the target VM, address: '127.0.0.1:59642', transport: 'socket'
spring-web:6.0.14
Send a request. Response is:
{"errcode":0,"errmsg":"ok","msgid":3229660303395831817}
Comment From: quaff
Here is a minimal reproducer:
import java.util.Collections;
import org.springframework.http.HttpEntity;
import org.springframework.web.client.RestTemplate;
public class SimpleTests {
public static void main(String[] args) {
System.out.println(new RestTemplate().postForObject("https://api.weixin.qq.com/cgi-bin/message/template/send",
new HttpEntity<>(Collections.emptyMap()), String.class));
}
}
6.1 will report error 412 Precondition Failed: [no body]
6.0 will print {"errcode":41001,"errmsg":"access_token missing rid: 65767ca2-541efdfa-204cc1a9"}
Comment From: poutsma
This is due to the fact that as of Spring Framework 6.1, most ClientHttpRequestFactory
implementations no longer buffer request bodies before sending them to the server. As a result, for certain content types such as JSON, the contents size is no longer known, and a Content-Length
header is no longer set. If you would like to buffer request bodies like before, simply wrap the ClientHttpRequestFactory
you are using in a BufferingClientHttpRequestFactory
.
This gets the expected "access_token missing" error:
RestTemplate restTemplate = new RestTemplate();
restTemplate.setRequestFactory(new BufferingClientHttpRequestFactory(restTemplate.getRequestFactory()));
System.out.println(restTemplate.postForObject("https://api.weixin.qq.com/cgi-bin/message/template/send",
new HttpEntity<>(Collections.emptyMap()), String.class));
Comment From: aliciz
I'm having the same problem now, I've changed it to define resttemplate this way, and that's fine, but I'm not sure if it's elegant, there's a better way?
@Bean
public RestTemplateBuilder restTemplateBuilder(RestTemplateBuilderConfigurer restTemplateBuilderConfigurer) {
RestTemplateBuilder builder = new RestTemplateBuilder();
return restTemplateBuilderConfigurer.configure(builder.requestFactory(new Function<ClientHttpRequestFactorySettings, ClientHttpRequestFactory>() {
@Override
public ClientHttpRequestFactory apply(ClientHttpRequestFactorySettings clientHttpRequestFactorySettings) {
return new BufferingClientHttpRequestFactory(new SkipSslVerificationHttpRequestFactory());
}
}));
}
@Bean
public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder) {
RestTemplate restTemplate = restTemplateBuilder.build();
List<HttpMessageConverter<?>> converters = restTemplate.getMessageConverters();
for (HttpMessageConverter<?> converter : converters) {
if (converter instanceof MappingJackson2HttpMessageConverter) {
try {
List<MediaType> mediaTypeList = new ArrayList<>(converter.getSupportedMediaTypes());
mediaTypeList.add(MediaType.TEXT_PLAIN);
((MappingJackson2HttpMessageConverter) converter).setSupportedMediaTypes(mediaTypeList);
} catch (Exception e) {
e.printStackTrace();
}
}
}
return restTemplate;
}
Comment From: bclozel
@aliciz it depends if you are using Spring Boot or not. I would ask the question on StackOverflow anyway.
Comment From: aliciz
@aliciz it depends if you are using Spring Boot or not. I would ask the question on StackOverflow anyway.
I using spring boot 3.2.1