Unable to Retrieve cookies when request is called using Spring RestTemplate - spring

I have two web applications. There is a HttpSession at second application and first application knows the sessionid of it.
I am making a request from First application to second application using RestTemplate by adding its session id to headers.
When the request is received at the second application, I am trying to read all its cookies from request. But, I only see the JSESSIONID cookie and don't get all the cookies that I set previously.
Suppose, I access the same url on the browser manually, I see all those cookies retrieved.
Request made in First application:
String sessionId = "6iuvgwy5ceqzwlxh646qo0ms";//SessionId of second application
String url = "http://example.com/data/retrieve";
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.add("Cookie", "JSESSIONID=" + sessionId);
HttpEntity<String> requestEntity = new HttpEntity<String>(null, requestHeaders);
ResponseEntity<String> responseEntity = restTemplate.exchange(url,
HttpMethod.GET, requestEntity, String.class);
If this can't be done using Spring RestTemplate, please suggest me if there is any other way of doing it.

There is no session cookie. Cookie is just a header.
You lind of reset the header to have only JSESSIONID.
To fix it change the logic a bit
You somehow get the session id (I guess from some request). Get not only the session but all the rest cookie as well and add them to the requestHeaders when you call the restTemplate.

Related

Send the HttpSession through restTemplate

How to send the HttpSession through the restTemplate to next microservice consider below exmple.
We have two miceoservices call A and B. We are calling some restTemplate call to service B.
But in the Service B we are getting attributes through httpServletRequest.getSession().getAttribute("name"); this is the limitations in service B.
So how to pass the HttpSession to service B from A?
You can pass the session through headers like this:
HttpHeaders headers = new HttpHeaders();
headers.add("Your-Session-Header-Name", serialize(session));
ResponseEntity<UUID> exchange = restTemplate.exchange(url, HttpMethod.GET,new HttpEntity<Void>(headers), UUID.class);
And read session from headers at the server side

Spring Boot RestTemplate WebClient - Response Body JSON Empty

I am using Rest Template and have used Web Client as well. I get the key in response but the body is empty always. Using Postman I can see the Response which is a JSON.
My code snippet is below -
HttpHeaders headers = new HttpHeaders();
headers.setBasicAuth("john", "doe");
HttpEntity<String> request = new HttpEntity<String>(headers);
ResponseEntity<String> response = restTemplate.exchange(
"https://www.getMeData.com",
HttpMethod.GET, request, String.class);
System.out.println(response.getBody());
Response is as below -
{"result":[]}
Has anyone faced the same issue?
In Postman the Response Headers I can see is -
KEY VALUE
Content-Encoding gzip
Content-Type application/json;charset=UTF-8
Transfer-Encoding chunked
I just changed the Restemplate exchange method parameter from String url to new URI("url") and it worked.
ResponseEntity<String> response = restTemplate.exchange(new URI("https://www.getMeData.com"),
HttpMethod.GET, request, String.class);
Try to add headers as below:
HttpHeaders headers = new HttpHeaders();
headers.setBasicAuth("john", "doe");
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> request = new HttpEntity<String>(headers);
For gZip - use
Gzip is disabled by default, check whether it's enabled on your application. If not enable Gzip with properties
server.compression.enabled=true
server.compression.mime-types=text/html,text/xml,text/plain,text/css,text/javascript,application/javascript,application/json
server.compression.min-response-size=1024
And add below encoding to test
headers.add(HttpHeaders.CONTENT_ENCODING, "gzip");
headers.add(HttpHeaders.ACCEPT_ENCODING, "gzip");
You can also try with creating a new Http message convertor and add the same to RestTemplate instance before invoking remote api call..
Spring implementation simply does not support it.
From the HTTP 1.1 2014 Spec:
A payload within a GET request message has no defined semantics;
sending a payload body on a GET request might cause some existing
implementations to reject the request.
Having that stated this is how you should refactor your code to make it work:
ResponseEntity<String> response = restTemplate.exchange(
"https://www.getMeData.com",
HttpMethod.POST, // <- this is it
request, String.class);
If you have no control over controller method layout - switch to python + requests library to have this done.

How to use OAuth2RestTemplate having only tokenValue?

The application starts when other application calls the starting endpoint with the access token as a paremeter. The access token is a type of string.
Then I have to call a few other endpoints where the authentication is based on that token.
Is it possible to create OAuth2RestTemplate to make requests having only tokenValue withouth access token uri?
As far as I know, you can achieve this by implementing the AccessTokenProvider interface and setting it:
https://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth2/client/token/AccessTokenProvider.html
Although, the OAuth2RestTemplate is exactly to simplify the use of this kind of flow for you. If your use will be straight forward maybe it's better for you to use the default RestTemplate and use the HTTP specification. So, for this, you should use an Authorization header of type Bearer. Like this:
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", "Bearer " + tokenValue);
And use this header in your requests, like this:
HttpEntity<String> request = new HttpEntity<String>(headers);
ResponseEntity<BodyClass> response = restTemplate.exchange(url, HttpMethod.GET, request, BodyClass.class);
BodyClass body = response.getBody();
Hope it helps.

301 ResponseCode in RestTemplate Client

I am trying to consume a service using RestTemplate in Spring. I tried around and each time getting 301 as response code. However, I am good to get a json response from the same uri while using POSTMAN.
Here is the code to get the statelist:
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
String baseUri = "http://www.whizapi.com/api/v2/util/ui/in/indian-states-list";
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(baseUri)
.queryParam("project-app-key","my-key");
HttpEntity<String> entity = new HttpEntity<String>("parameters", headers);
ResponseEntity<String> stats = restTemplate.exchange(builder.build().toUri(),
HttpMethod.GET,entity ,String.class);
Please suggest if I am missing anything.
HTTP 301 is a permanent redirect. You are accessing an outmoded url.
Having checked this url http://www.whizapi.com/api/v2/util/ui/in/indian-states-list redirected to https://www.whizapi.com/api/v2/util/ui/in/indian-states-list.ashx.
The same can be seen in Location response header as shown in the below image.
So, you should directly request https://www.whizapi.com/api/v2/util/ui/in/indian-states-list.ashx from your restTemplate object.
More details could be found here
Hope this helps!

Spring RestTemplate session

I'm trying to use spring rest template to do a post request to login in.
When I receive the response in my first request i store my session id which is received via cookie. I retrieve it in a set-cookie response header which i get via:
//first request
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
LinkedMultiValueMap<String, Object> mvm = new LinkedMultiValueMap<String, Object>();
mvm.add("LoginForm_Login", "login");
mvm.add("LoginForm_Password", "password");
ResponseEntity<String> result = restTemplate.exchange(uriDWLogin, HttpMethod.POST, requestEntity, String.class);
result.getHeaders().get("Set-Cookie").stream().forEach(System.out::println);
then in every subsequent request i set the Cookie request header with the values received in the first request:
//subsequent request
RestTemplate restTemplate = new RestTemplate(); HttpHeaders headers = new HttpHeaders();
headers.set("Cookie",cookies.stream().collect(Collectors.joining(";")));
HttpEntity<String> entity = new HttpEntity<String>(headers);
RestTemplate.exchange("http://url", HttpMethod.POST, entity, String.class);
all goes well for the second request, but I can not keep the session for the others requests
You will need to use some kind of cache to store your access token.
When you'll be accessing downstream service, you take the token from cache. If cache doesn't contain token, you will authenticate and retrieve it and store to cache first.
Caching is always tricky topic, because it has to be thread-safe. I would try to avoid servlet sessions. You are consuming service, not being consumed.
There are various caching options, but as you are already using Spring, spring caching may be good fit. Take a look at this Spring Cache guide to start.

Resources