RestTemplate POST request urlformencoded gives 400 (Bad Request) - spring

I have the following request :
String url = "url to oauth_token";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
RestTemplate restTemplate = new RestTemplate();
String body = "grant_type=authorization_code&client_id=123&client_secret=123&"
+ "redirect_uri=https://axyz.com&code=123";
HttpEntity<Object> entity = new HttpEntity<>(body, headers);
Object token = restTemplate.exchange(url, HttpMethod.POST, entity, Object.class);
This seems to return 400 (Bad Request). I have also tried its alternatives where body is a MultiValueMap but this is what makes the most sense to me. Is there something wrong with the way I am trying the request?

The values of the POST fields should be URL encoded (you can use URLEncoder.encode(value, "UTF-8") for each value while concatenating the body string). That's why you get 400 error.
You'd better use a more convenient way to create a POST form entity with keys and values, which will URL encode your values automatically:
List<NameValuePair> formparams = new ArrayList<NameValuePair>();
formparams.add(new BasicNameValuePair("param1", "value1"));
formparams.add(new BasicNameValuePair("redirect_uri", "https://axyz.com"));
...
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparams, Consts.UTF_8);

Related

response from post request is empty

I have the following WS i request from post man with the following parameters:
and i have the following from the postman console
I am trying to request the WS with the following piece of code :
logger.info("generating new token from "+URL);
expritation = new Date();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
MultiValueMap<String, String> map= new LinkedMultiValueMap<>();
map.add("userUid", userUid);
map.add("appUid", appUid);
map.add("ttl", ttl);
restTemplate.getInterceptors().add(new BasicAuthorizationInterceptor(WsLogin, WsPassword));
ResponseEntity<String> response = restTemplate.postForEntity(URL, map , String.class);
return response.getBody();
I am able to see the response body in postman but the response.getBody() is emty in the java code.
Can someone explain to me why it is the case.
You mean you are seeing the response body in the Postman but not in your prog? Did you try to debug of print the response value before returning from the method?

How to retrieve all Cookies from REST Template?

I am working on a project where I want to send a POST REST call and get the response and in the response, there are few cookies. among those, I want to get X-Bonita-API-Token and pass it to the frontend.
I used String set_cookie = httpHeaders.getFirst(HttpHeaders.SET_COOKIE); this return only the first cookie but i need the second.
my code
final String uri = "http://localhost:8080/bonita/loginservice";
RestTemplate template = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
HttpEntity<ApiRequest> entity = new HttpEntity<>(apiRequest, headers);
template.getMessageConverters().add(getMappingJackson2HttpMessageConverter());
HttpEntity<String> response = template.exchange(uri, HttpMethod.POST, entity,String.class);
HttpHeaders httpHeaders = response.getHeaders();
String set_cookie = httpHeaders.getFirst(HttpHeaders.SET_COOKIE);
Here are the returned cookies.
can anyone help me to retrieve X-Bonita-API-Token?
Thanks.

Passing RequestParam data to Spring RestController

I am using restTemplate.exchangemethod to invoke one service from another service.My request url does accept a request parameter.
url is of the formhttp://localhost:8035/sgapp/student/fetchDeptNo?sid
In the conttroller it is written as
#RestController
#RequestMapping(value="/sgapp/student")
public class SiController{
#GetMapping(value = "/fetchDeptNo",consumes = "application/x-www-form-urlencoded")
public ResponseEntity<String> getSid(#RequestParam(name = "sid")String sid){
String sid = myRepo.getSidCode(sid);
System.out.println("sid received from DB::"+sid);
return new ResponseEntity<String>(sid,HttpStatus.OK);
}
}
In the caller application I am invoking it as
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
HttpEntity<?> entity = new HttpEntity<>(headers);
Map paramMap = new HashMap<String, String>();
paramMap.put("sid", sidData);
HttpEntity<String> sidRespnse = restTemplate.exchange(
"http://localhost:8035/sgapp/student/fetchDeptNo", HttpMethod.GET, entity, String.class,
paramMap);
But I'm getting folllowing exception:
org.springframework.web.client.HttpClientErrorException: 400 null
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:94) ~[spring-web-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:79) ~[spring-web-5.0.6.RELEASE.jar:5.0.6.RELEASE]
Can anyone provide any suitable solution to this???
That particular exchange method is used to substitute variables into the path.
If you want to pass query parameters, use UriComponentsBuilder to create the URL with query params:
UriComponentsBuilder builder =
UriComponentsBuilder
.fromHttpUrl(rootUri)
.queryParam("sid", sidData);
Then you can use RestTemplate as follows:
restTemplate.exchange(
builder.toUriString(),
HttpMethod.GET,
entity,
String.class);

How to not escape form body characters in Spring RestTemplate when making a POST request?

I have following code where I am making a POST form request. The request body contains username and password. Password contains # characters, which is replaced by RestTemplate with %40 and I am getting "unauthorized" error as the password is wrong now.
Following is the debug info from bufferOutput(request body)
merchant_id=firstname+de-lastname%40gmail.com&password=%40Password
Here is the code snippet that is making the call.
MultiValueMap<String, String> formData = new LinkedMultiValueMap<String, String>();
String url = "SOME_URL";
formData.add("username", "xay#gmail.com");
formData.add("password", "#name321");
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
HttpEntity<MultiValueMap<String,String>> requestEntity = new HttpEntity<MultiValueMap<String,String>>(formData,headers);
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters()
.add(0, new StringHttpMessageConverter(Charset.forName("UTF-8")));
restTemplate.exchange(url, HttpMethod.POST, requestEntity, Authentication.class,"321");
The question is how to tell restTemplate not to escape body data ?
Note that the request has to be a post form request and I can not use UriComponentsBuilder to fix the problem.
I think you need to add a FormHttpMessageConverter to your RestTemplate rather than a StringHttpMessageConverter.

HTTP get with headers using RestTemplate

How can I send a GET request using the Spring RestTemplate?
Other questions have used POST, but I need to use GET.
When I run this, the program continues to work, but it seems that the network is clogged because this is in an AsyncTask, and when I try to run another asynctask after I click on the button for this one, they won't work.
I tried doing
String url = "https://api.blah.com/2.0/search/cubes?w=jdfkl&whitespace=1";
MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
map.add("Bearer", accessToken);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); //copied this from somewhere else, not sure what its for
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(map, headers);
HttpMessageConverter<String> stringConverter = new StringHttpMessageConverter();
FormHttpMessageConverter formConverter = new FormHttpMessageConverter();
List<HttpMessageConverter<?>> msgConverters = new ArrayList<HttpMessageConverter<?>>();
msgConverters.add(formConverter);
msgConverters.add(new MappingJacksonHttpMessageConverter());
msgConverters.add(stringConverter);
template.setMessageConverters(msgConverters);
//SetSearchResponseData is my custom class to store the incoming JSON
ResponseEntity<SetSearchResponseData> result = template.exchange(url, HttpMethod.GET, request, SetSearchResponseData.class);
//If I was using post, i could have done SetSearchResponseDataresponse = restTemplate.postForObject(url, request, SetSearchResponseData.class);
The RestTemplate getForObject() method does not support setting headers. The solution is to use the exchange() method.
So instead of restTemplate.getForObject(url, String.class, param) (which has no headers), use
HttpHeaders headers = new HttpHeaders();
headers.set("Header", "value");
headers.set("Other-Header", "othervalue");
...
HttpEntity<Void> requestEntity = new HttpEntity<>(headers);
ResponseEntity<String> response = restTemplate.exchange(
url, HttpMethod.GET, requestEntity, String.class, param);
Finally, use response.getBody() to get your result.
This question is similar to this question.
Take a look at the JavaDoc for RestTemplate.
There is the corresponding getForObject methods that are the HTTP GET equivalents of postForObject, but they doesn't appear to fulfil your requirements of "GET with headers", as there is no way to specify headers on any of the calls.
Looking at the JavaDoc, no method that is HTTP GET specific allows you to also provide header information. There are alternatives though, one of which you have found and are using. The exchange methods allow you to provide an HttpEntity object representing the details of the request (including headers). The execute methods allow you to specify a RequestCallback from which you can add the headers upon its invocation.
The getForObject() method of RestTemplate does not support setting headers. you can use this
syntax:
restTemplate.exchange(url endpoint,
HttpMethod.GET,entity, params)
public List<Employee> getListofEmployee()
{
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
HttpEntity<String> entity = new HttpEntity<String>(headers);
ResponseEntity<List<Employee>> response = restTemplate.exchange("http://hello-server/rest/employees",
HttpMethod.GET,entity, new ParameterizedTypeReference<List<Employee>>() {});
return response.getBody(); //this returns List of Employee
}

Resources