It's been troubling for a couple days already for a seemingly super straightforward question:
I'm making a simple GET request using RestTemplate in application/json
, but I keep getting
org.springframework.web.client.HttpClientErrorException: 400 Bad Request
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:91)
at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:636)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:592)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:552)
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:470)
I did research and followed this tutorial, also I looked at solutions from this POST request via RestTemplate in JSON. But none of them helped, here's my code:
RestTemplate restTemplate = new RestTemplate();
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<?> requestEntity = new HttpEntity<Object>(requestHeaders);
restTemplate.exchange(endpoint, HttpMethod.GET, requestEntity, String.class);
endpoint
is http://localhost:8080/api/v1/items?itemIds=" + URLEncoder.encode(itemIds, "UTF-8")
which works fine in Postman.
itemIds
is a comma-separated list like below:
5400028914,5400029138,5400029138,5400029138,5400029138,5400028401,5400028918,5400028076,5400028726
I also tried to use getForObject
like below:
String result = restTemplate.getForObject(endpoint, String.class);
which gives me this error:
org.springframework.web.client.HttpClientErrorException: 415 Unsupported Media Type
I'm not sure what I missed or did wrong, but the same endpoint works perfectly on Postman, but the only difference is that I added Content-Type header in Postman app.
This is my Request from Postman:
GET /api/v1/items?itemIds=abc%2cdef%2cghi HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Postman-Token: 84790e06-86aa-fa8a-1047-238d6c931a68
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36
Content-Type: application/json
Accept: */*
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8,zh-CN;q=0.6,zh;q=0.4
So how can I correctly set content-type using RestTemplate if my above code is wrong?
Another deep dive, I've fired up Wireshark to capture the two HTTP requests, here are the screenshots:
The request from my Java code:
I still don't see why the one from my Java program throws 400 while the one from Postman works fine.
Thanks a lot.
OK, eventually, one of my co-workers helped me figure out why, believe it or not, it's this simple:
The endpoint
was like this:
"http:localhost:8080/api/v1/items?itemIds=" + URLEncoder.encode(itemIds, "UTF-8");
However, it should be "http:localhost:8080/api/v1/items?itemIds=" + itemIds;
itemIds
is just a comma-separated list.
After URLEncoder encoding via "UTF-8" schema, this comma-separated list becomes itemIds=5400028914%2C5400029138%2C5400029138%2C5400029138%2C5400029138%2C5400028401%2C5400028918%2C5400028076
from
itemIds=5400028914,5400029138,5400029138,5400029138,5400029138,5400028401,5400028918,5400028076,5400028726
We don't need to URLEncoder to encode the URL when using RestTemplate, anyone could help me deepen my understanding here please?
Thanks!