Cannot fetch response from the header (Spring boot, Webclient) - spring-boot

Hi I am new here and this is my first Post.
I am writing testcases for a class in which I am trying to fetch response from the header (Spring boot, Webclient, Mockito) and I am getting below error
"Cannot invoke "org.springframework.http.HttpHeaders.get(Object)" because "responseHeaders" is null"
I am relatively new to springboot please let me know if I am missing any details.
Service Class code:
log.debug("Fetching CSRF token");
HttpHeaders newHeader = new HttpHeaders();
ResponseEntity<String> response = webClient
.get()
.uri(s4Url)
.header(XCSRFTOKEN, "Fetch")
.retrieve()
.toEntity(String.class)
.block();
if(null != response) {
System.out.println(response);
HttpHeaders responseHeaders = response.getHeaders();
System.out.println(responseHeaders);
//Failing at below line
String csrfToken = responseHeaders.get(XCSRFTOKEN).get(0);
log.debug("*** S4 Token :" + csrfToken);
log.info("*** Token call response code:" + response.getStatusCodeValue());
Test Class Code:
doReturn(requestHeadersUriSpec).when(webClient).get();
doReturn(requestHeadersSpec).when(requestHeadersUriSpec).uri(getRetrieveUrl());
doReturn(requestHeadersSpec).when(requestHeadersSpec).header(XCSRFTOKEN, "Fetch");
doReturn(responseSpec).when(requestHeadersSpec).retrieve();
doReturn(responseEntityMono).when(responseSpec).toEntity(String.class);
doReturn(expectedHttpHeaders).when(responseEntityMono).block();
HttpHeaders actualResponseHeader = s4PostCall.fetchToken(s4Url);

Related

How to add file as Form data in Http request in spring boot

I'm writing test cases to a controller in spring boot which takes MultipartFile as RequestParam. In the test case method I'm using TestRestTemplate.exchange() to send the request to the controller. I'm not sure how to make the Headers correctly so that I can send the request.
The Postman curl looks like this:
curl --location --request POST 'localhost:9091/response/upload'
--form 'file=#"/home/adityak/Downloads/ClientLog_NEW.txt"'
For file uploading to any service or endpoint
private String testExchange(File file) {
//add file
LinkedMultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
params.add("file", new FileSystemResource(file));
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
HttpEntity<LinkedMultiValueMap<String, Object>> requestEntity =
new HttpEntity<>(params, headers);
ResponseEntity<String> responseEntity = restTemplate.exchange(
"/upload-file",
HttpMethod.POST,
requestEntity,
String.class);
HttpStatus statusCode = responseEntity.getStatusCode();
if (statusCode == HttpStatus.ACCEPTED) {
result = responseEntity.getBody();
}
return result;
}

How to read response with Content-Type text/plain;charset=UTF-8 using RestTemplate

I have an API (/get-sas-token) that is returning a response with Content-Type=text/plain;charset=UTF-8.
In Postman when I hit this API it returns as sig=PAd%2By7yzue0G%2FVeMKbwvR%2F%2B5a3X8CUTablCIhS3uCuk%3D&s
The code for this API is
#GetMapping("/get-sas-token/{containerName}")
public String getSASToken(#PathVariable("containerName") String containerName)
throws InvalidKeyException, URISyntaxException, StorageException {
CloudBlobContainer appcontainer = config.blobClient().getContainerReference(containerName);
return appConfiguration.generateSASToken(appcontainer);
}
My other microservice is trying to call this RestAPI using RestTemplate via a get request. The response I'm getting in Postman has instead of special characters like �������{J�J��t�\b�`$ؐ#������iG# some weird stuff. So I guess somethings wrong with the character encoding.
P.S : If I remove the Accept-Encoding(gzip, deflate, br) header from Postman it works.How can i get it working in my code
ResponseEntity<String> imageUrl = restTemplate.exchange(
fileServiceUrl + "/get-sas-token/" + containerReference, HttpMethod.GET, request, String.class);
logger.info("imageUrl body-------->>" + imageUrl.getBody());
It prints
imageUrl body-------->>?`I?%&/m?{J..................
I have tried all the possible soultions but nothing works for me
tried this::
template.getMessageConverters()
.add(0, new StringHttpMessageConverter(Charset.forName("UTF-8")));
ResponseEntity<Object> response = template.exchange(endpoint, method, entity,
Object.class);
Also this::
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.set("Accept", "application/json");

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

Null response entity with 307 status code in Rest Template

I am trying to use Spring RestTemplateBuilder to call a REST web service and POST data. Here is the sample of my code.
public HttpHeaders getHttpHeaders() {
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.add("Authorization", "Basic " + authToken);
requestHeaders.add("Content-Type", "application/json");
return requestHeaders;
}
public ResponseJson getData(RequestJson requestJson) {
HttpEntity<RequestJson> entity = new HttpEntity<>(requestJson, getHttpHeaders());
ResponseEntity<ResponseJson> result = restTemplateBuilder.build().postForEntity(PostUrl, entity, ResponseJson.class);
}
When I debug this, it gives status=307 and body=null for ResponseEntity. But when I call the PostUrl directly with a request body, it creates data with 201 status code.
May I know how, to figure out this 307 status and why I am getting null response ?
This works for me, using HttpComponentsClientHttpRequestFactory https://lateralcoding.blogspot.com/2018/03/Spring-RestTemplate-AutoRedirect.html

RestTemplate call returns 401 Unauthorized

Background
I am trying to consume a REST endpoint hosted on IBM Cloud API from my SpringBoot application using RestTemplate. I am using the following snippet to make the call:
RestTemplate send = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setCacheControl(CacheControl.noCache());
headers.set("x-ibm-client-id", clientId);
headers.set("x-ibm-client-secret", clientSecret);
HttpEntity<BodyEntity> httpEntity = new HttpEntity<>(bodyEntity, headers);
send.exchange(ENDPOINT_URL, HttpMethod.POST, httpEntity, Object.class);
I used the following snippet to configure RestTemplate
#Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder.build();
}
Problem
Using this snippet, when the call is made I receive 401 Unauthorized. When I made the same call using Postman, I received correct response from server without any problem.
Since I received 401 response code I set to further investigate the request by logging headers and body and other parts of request.
I implemented ClientHttpRequestInterceptor to log outgoing requests to further debug the issue and added this interceptor to my RestTemplate config as follows:
#Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
// new code
builder.interceptors(new LoggingClientHttpRequestInterceptor());
return builder.build();
}
After making the request again, I could see in the log that the outgoing call contained all details as it should e.g. Headers and Body were correct.
After this, I changed the whole thing to use Apache HTTP Client as follows:
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost(URL);
String reqString = "BODY";
httpPost.setEntity(new StringEntity(reqString, ContentType.APPLICATION_JSON));
httpPost.setHeader("accept", "application/json");
httpPost.setHeader("content-type", "application/json");
httpPost.setHeader("cache-control", "no-cache");
httpPost.setHeader("x-ibm-client-id", clientId);
httpPost.setHeader("x-ibm-client-secret", clientSecret);
CloseableHttpResponse response = httpClient.execute(httpPost);
try {
System.out.println("Response status: " + response.getStatusLine());
HttpEntity entity1 = response.getEntity();
System.out.println("Response :" + entity1.toString());
} finally {
response.close();
}
Using the snippet above, I executed the request and received correct response.
Question
Why RestTemplate call returns and error whereas HttpClient returns correct response?
Do I need to further configure RestTemplate?
What have I missed?

Resources