'http POST request: curl and postman both succeeded but resttemplate gives 400 Bad Request
I'm trying to convert a curl (also proved working in postman) query to java resttemplate:
$ curl -X POST https://my.server/apiv2/login -k -H 'Accept: application/json' -H 'Content-Type: application/json' -d '{"password":"forgetme","userName":"myname"}'
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 593 100 492 100 101 1817 373 --:--:-- --:--:-- --:--:-- 2196{"token":"sometoken",...}
However, the following code gives 404 error
JSONObject payload = new JSONObject();
payload.put("userName", this.serviceAccount);
payload.put("password", this.password);
HttpHeaders headers = new HttpHeaders();
headers.add("Accept", MediaType.APPLICATION_JSON.toString());
headers.add("Content-Type", MediaType.APPLICATION_JSON.toString());
HttpEntity<String> entity = new HttpEntity<String>(payload.toString(), headers);
ResponseEntity<Response> result =
this.restTemplate.exchange(tokenUrl.toString(), HttpMethod.POST, entity, Response.class);
I verified that the url, user name, and password are all correct.
2022-05-14 04:04:03 [scheduling-1] ERROR *** url =https://my.server/apiv2/login
2022-05-14 04:04:03 [scheduling-1] ERROR *** entity = <{"password":"forgetme","userName":"myname"},[Accept:"application/json", Content-Type:"application/json"]>
The only thing which seems to be related is that in the entity, application/json is enclosed by double quotes and if I put double quotes in curl around application/json, the query would fail (no response at all.
If I change the entity construction code to
HttpEntity<JSONObject> entity = new HttpEntity<JSONObject>(payload, headers);
I will get 400 Bad Request exception
==================================================== I would not post this as an answer until I understand why. I managed to make it work by initializing the resttemplate as following:
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
requestFactory.setConnectTimeout(300000);
requestFactory.setReadTimeout(300000);
this.restTemplate = new RestTemplate(requestFactory);
this.restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
this.restTemplate.getMessageConverters().add(new FormHttpMessageConverter());
this.restTemplate.setErrorHandler(new MyThrowErrorHandler());
public class MyThrowErrorHandler implements ResponseErrorHandler {
@Override
public boolean hasError(ClientHttpResponse response) throws IOException {
return false;
}
@Override
public void handleError(ClientHttpResponse response) throws IOException {
}
}
I understand that it ignores exception but the query is actually successful and I've got the response as expected. So my question now is if it's indeed a BAD REQUEST, how the above extra code fixes the bad request.
Solution 1:[1]
In these kind of scenarios, you could try debugging payload. I use https://req.dothttp.dev/ to preview curl of the request.
replace url with https://req.dothttp.dev/https://my.server/apiv1/login
and compare with working curl statement.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | cedric |