401 Error accessing Rest API passing get_cookie - spring

I am accessing an API which expects me to make a POST call to their Login endpoint and then make subsequent calls to get data. The call I make to their login endpoint works. But the subsequent call to get data throws a 401 error. This is the error I get
org.springframework.web.client.HttpClientErrorException: 401 Unauthorized
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:91)
at org.springframework.web.client.RestTemplate.handleResponseError(RestTemplate.java:615)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:573)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:544)
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:465)
at com.wsc.eventconsumer.phonex.api.InventoryServiceImpl.getProducts(InventoryServiceImpl.java:70)
Now this works fine when I use Postman and the Restlet client. I noticed that in Restlet client the GET call to the API passes a cookie that was set by the API in the login call. I tried passing the response headers from the login call in the GET request. But I still get a 401. I am using the standard resttemplate configuration.
<bean id="restTemplate" class="org.springframework.web.client.RestTemplate"/>
HttpEntity<Credentials> entity = new HttpEntity<Credentials>(credentials, headers);
ResponseEntity<String> response = restTemplate.exchange(loginEndpoint, HttpMethod.POST, entity, String.class);
HttpHeaders rHeaders = response.getHeaders();
HttpEntity<String> request = new HttpEntity<String>(rHeaders);
ResponseEntity<Product[]> response2 = restTemplate.exchange(productEndpoint,
HttpMethod.GET, request, Product[].class);

Related

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.

Unauthorized 401 error for GET call on stockitem

I am accessing Acumatica API using Java Spring Resttemplate. The POST call to the Login endpoint works fine. But the next call to get StockItems gets a 401 Unauthorized error.
org.springframework.web.client.HttpClientErrorException: 401 Unauthorized at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:91) at org.springframework.web.client.RestTemplate.handleResponseError(RestTemplate.java:615) at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:573) at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:544) at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:465) at
Now this works fine when I use Postman and the Chrome Restlet client. I noticed that in Restlet client the GET call to the API passes a session cookie that was set by the API in the login call. I tried passing the response headers from the login call in the GET request. But I still get a 401. I am using the standard resttemplate configuration.
HttpEntity<Credentials> entity = new HttpEntity<Credentials>(credentials, headers);
ResponseEntity<String> response = restTemplate.exchange("https://xxxx.acumatica.com/entity/auth/login",
HttpMethod.POST, entity, String.class);
HttpHeaders rHeaders = response.getHeaders();
String set_cookie = rHeaders.getFirst(rHeaders.SET_COOKIE);
if (LOG.isInfoEnabled()) { LOG.info("Response: " + response.toString()); }
if (LOG.isInfoEnabled()) { LOG.info("Set-Cookie: " + set_cookie); }
HttpEntity<String> entity2 = new HttpEntity<String>(response.getHeaders());
ResponseEntity<String> response2 = restTemplate.exchange("https://usell.acumatica.com/entity/Default/6.00.001/StockItem?$expand=Attributes,WarehouseDetails", HttpMethod.GET, entity2, String.class);
How did Acumatica API client using Java get around this problem?
I was not setting all the cookies.. this is all I had to do
List<String> cookies = response.getHeaders().get(HttpHeaders.SET_COOKIE);
HttpHeaders requestHeaders = new HttpHeaders();
for (String cookie : cookies) {
requestHeaders.add("Cookie", cookie);
}

400 Bad Request for Spring RestTemplate and GET on Salesforce.com Connected Apps

Having an issue to create a basic API to the Salesforce.com object queries using Connected Apps and a Spring RestTemplate client. The inital authentication step using a POST operation is working fine and returns the Salesforce instance URL as well as the required access-token. The following GET operation fails with an Error 400. The URL and access-token were both validated by a Chrome POSTMAN plugin, that in combination returns a valid JSON response.
It is also worth to mention that the traditional implementation has not worked well and that "setAccept" was a later attempt to try to solve the parsing of the mediatype.
Below the code in error:
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Collections.singletonList(MediaType.parseMediaType("application/json")));
headers.add("User-Agent", USER_AGENT);
headers.add("Authorization", "Bearer " + accessToken);
HttpEntity<String> request = new HttpEntity<String>(headers);
ResponseEntity<String> responseBodyForGet = restRetrieveSalesforceData
.exchange(url, HttpMethod.GET, request, String.class);
The solution found to fix the 400 bug at the Spring RestTemplate GET operation is the following:
URI targetUrl = UriComponentsBuilder.fromUriString(url).build().toUri();
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", "Bearer " + accessToken);
HttpEntity<String> request = new HttpEntity<String>(headers);
logger.info("Requesting GET from: " + url);
ResponseEntity<String> responseBodyForGet = restRetrieveSalesforceData.exchange(targetUrl,
HttpMethod.GET, request, String.class);
I've added the solution to the report posted above. Observe the use of the first statement UriComponentsBuilder, which solved the 400 issue at the GET.

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!

Unable to Retrieve cookies when request is called using Spring RestTemplate

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.

Resources