How to retrieve all Cookies from REST Template? - spring

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.

Related

Kerberos client - kerberoRestTemplate not working

Im trying to consume an api which is authenticating with Kerberos. I have referred the below spring documentation related to KerberosRestTemplate.reference link, im passing the correct keytab file and the userPrincipal values as mentioned in the reference doc. But still im receiving 401 from the server.
But when I execute the kinit command in the terminal it receives a ticket from KDC and with that, im able to execute the curl command and get a working response.
KerberosRestTemplate kerberosRestTemplate = new KerberosRestTemplate("svc_dfsd.keytab", "svc_dfsd#sswe.AD");
String url="https://wexample.com:20550/aggr_subscriber_summary_hbase/03434809824";
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.TEXT_XML));
HttpEntity<String> entity = new HttpEntity<String>("parameters", headers);
ResponseEntity<String> response = kerberosRestTemplate.exchange(url, HttpMethod.GET, entity, String.class);
Can you suggest any other better approach to do this or fix this. All your comments are highly appreciated!!!
Troubleshooting Kerberos might be tricky since the errors are often misleading and Java implementation does a lot if implicit actions (canonicalization of URLs, etc.).
I suggest trying Kerb4J library which allows you to generate the kerberos token explicitly:
SpnegoClient spnegoClient = SpnegoClient.loginWithKeyTab("svc_dfsd#sswe.AD", "svc_dfsd.keytab");
SpnegoContext context = spnegoClient.createContext("https://wexample.com"); // Will result in HTTP/wexample.com SPN
RestTemplate restTemplate = new RestTemplate();
String url="https://wexample.com:20550/aggr_subscriber_summary_hbase/03434809824";
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.TEXT_XML));
headers.add("Authorization", context.createTokenAsAuthroizationHeader());
HttpEntity<String> entity = new HttpEntity<String>("parameters", headers);
ResponseEntity<String> response = restTemplate .exchange(url, HttpMethod.GET, entity, String.class);
If default SPN resolution works for you, you can also use SpnegoRestTemplate from this Kerb4J:
SpnegoClient spnegoClient = SpnegoClient.loginWithKeyTab("svc_dfsd#sswe.AD", "svc_dfsd.keytab");
SpnegoRestTemplate spnegoRestTemplate = new SpnegoRestTemplate(spnegoClient);
String url="https://wexample.com:20550/aggr_subscriber_summary_hbase/03434809824";
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.TEXT_XML));
HttpEntity<String> entity = new HttpEntity<String>("parameters", headers);
ResponseEntity<String> response = spnegoRestTemplate.exchange(url, HttpMethod.GET, entity, String.class);
Disclaimer: I'm the author of Kerb4J

Sending multipart requests using Spring Boot with specific header for every part

Postman request
As mentioned in image I would like to send content-type as application/json for a particular part of a multipart request in springboot application.
use MultipartBodyBuilder to build your request.
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
headers.add("add custome header", "header value");
MultipartBodyBuilder builder = new MultipartBodyBuilder();
builder.part("json_part", "").header("Content-Type", "application/json");
MultiValueMap<String, HttpEntity<?>> body = builder.build();
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity(body,
headers);
RestTemplate restTemplate = new RestTemplateBuilder().build();
ResponseEntity<String> postResponse = restTemplate
.postForEntity("yoururl", requestEntity, 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.

RestTemplate POST request urlformencoded gives 400 (Bad Request)

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);

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