How to get response from DHL Api to browser - spring-boot

i have problem with api from dhl, i create GET api from dhl, when print in console, result will print, but when using browser i got response like this :
com.squareup.okhttp.internal.http.RealResponseBody#68bd3d26
this my code :
#RequestMapping("/getData")
public String getAcc() throws IOException
{
OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/json");
HttpUrl httpUrl = new HttpUrl.Builder()
.scheme("https")
.host("api-eu.dhl.com")
.addPathSegment("track")
.addPathSegment("shipments")
.addQueryParameter("trackingNumber", "cencored")
.addQueryParameter("service", "express")
.build();
Request request = new Request.Builder()
.addHeader("content-type", "application/json")
.addHeader("Connection", "close")
.addHeader("DHL-API-Key", "cencored")
.addHeader("ConsumerKey", "cencored")
.addHeader("ConsumerSecret", "cencored")
.removeHeader("Content-Encoding")
.removeHeader("Content-Length")
.url(httpUrl) // <- Finally put httpUrl in here
.build();
response = client.newCall(request).execute();
System.out.println(response.body().string());
return this.response.body().toString();
}

solved...
this is weird, but work for me.
so we can't call "response.body().string();" twice.

This is the correctly way to consume a soap webservice with spring boot: https://spring.io/guides/gs/consuming-web-service/
Follow this tutorial and it works fine.

Related

REST API call from spring boot not working

I am trying to fetch live data from NSE options trading. Below code is not working and the request made is stuck without any response.
Any workaround on this?
public void getLiveBankNiftyData() {
String RESOURCE_PATH = "https://www.nseindia.com/api/option-chain-indices?symbol=BANKNIFTY";
ResponseEntity<Object[]> responseEntity = restTemplate.getForEntity(RESOURCE_PATH, Object[].class);
Object[] objects = responseEntity.getBody();
}
i tried this
// request url
String url = "https://www.nseindia.com/api/option-chain-indices?symbol=BANKNIFTY";
// create an instance of RestTemplate
RestTemplate restTemplate = new RestTemplate();
// make an HTTP GET request
String json = restTemplate.getForObject(url, String.class);
// print json
System.out.println(json);
I found a way out. Instead of using RestTemplate I used WebClient and this solved the issue.

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?

Get value from response body in RestClient

I am using Rest client of Firefox. I want to get value from response that is showing on Response body(Raw) in Rest-Client. I want to get this value in SpringBoot. Is it possible? If yes then How?
I have tried too many times but didn't get Satisfactory solution.
Using a Spring RestTemplate to make the calls will return a ResponseEntity. The simplest way to get the raw response would be this:
RestTemplate restTemplate = new RestTemplate();
try{
ResponseEntity<String> response = restTemplate.getForEntity(URI.create("http://example.org"),String.class);
System.out.println(response.getBody());
} catch (RestClientResponseException exception){
System.out.println(String.format("Error code %d : %s",e.getStatusCode().value(),e.getResponseBodyAsString()));
HttpHeaders errorHeaders = e.getResponseHeaders();
}
The ResponseEntity class will allow you to access the headers as well.
For more information on RestTemplate you can look at the docs here.

Spring RestTemplate receives "401 Unauthorized"

I am using the following to retrieve JSON via RestTemplate in Spring 4:
protected DocInfoResponse retrieveData(String urlWithAuth) {
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", "Basic " + auth.getSig());
HttpEntity<String> request = new HttpEntity<String>(headers);
ResponseEntity<DocInfoResponse> response = restTemplate.exchange(urlWithAuth, HttpMethod.GET, request, DocInfoResponse.class);
return response.getBody();
}
I used the same code (with different response class) to successfully get a JSON doc from the same site (with different parameters to get a different doc).
When I execute the above code I receive the following stack trace (in part):
Caused by: org.springframework.web.client.HttpClientErrorException: 401 Unauthorized
at
org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:91) ~[spring-web-4.3.7.RELEASE.jar:4.3.7.RELEASE]
Can anyone point me to why this might be receiving the exception?
I found that my issue originally posted above was due to double encryption happening on the auth params. I resolved it by using UriComponentsBuilder and explicitly calling encode() on the the exchange().
SyncResponse retrieveData(UriComponentsBuilder builder) {
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.set("Accept", MediaType.APPLICATION_JSON_VALUE);
HttpEntity<String> request = new HttpEntity<String>(headers);
ResponseEntity<SyncResponse> response = restTemplate.exchange(builder.build().encode().toUri(), HttpMethod.GET, request, SyncResponse.class);
return response.getBody();
}
My UriComponentsBuilder was built using:
UriComponentsBuilder buildUrl(String urlString) {
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(urlString);
return auth.appendAuth(builder);
}
(The auth.appendAuth() adds additional .queryParams() needed by the target service in urlString.)
The call to execute this was retrieveData(buildUrl(urlString));.
After investigating on my own problem, I realized that FireFox RESTClient was successful because I was connected to the target URL. The Basic Auth I thought I was using, was not so basic after all.
Eventually, I read the doc of the app i was trying to connect to and realized they propose a connection token mechanism. Now it works.
After reading your code, I say it looks quite OK, although I'm not sure what is your object auth on which you call getSig.
First things first: try to access your service from any client, like a web browser, a PostMan or RESTClient. Make sure you successfully retrieve your infos WITHOUT being connected to your app!!!
Depending on the result, I say you should, either try to encrypt manually your Authorization token (you'll easilly find posts on this site to show you how to) or try another connection mechanism.
The process of creating the Authorization header is relatively straightforward for Basic Authentication, so it can pretty much be done manually with a few lines of code:
HttpHeaders createHeaders(String username, String password){
return new HttpHeaders() {{
String auth = username + ":" + password;
byte[] encodedAuth = Base64.encodeBase64(
auth.getBytes(Charset.forName("US-ASCII")) );
String authHeader = "Basic " + new String( encodedAuth );
set( "Authorization", authHeader );
}};
}
Then, sending a request becomes just as simple:
RestTemplate restTemplate = new RestTemplate();
restTemplate.exchange
(uri, HttpMethod.POST, new HttpEntity<T>(createHeaders(username, password)), clazz);
https://www.baeldung.com/how-to-use-resttemplate-with-basic-authentication-in-spring#manual_auth

Apache HttpClient return cached body on conditional request

I'm using CachingHttpClient implementation of HttpClient from Apache. And having the following scenario:
I made a request for a resource that returned a response with a header:
Cache-Control:max-age=5.
So CachingHttpClient caches the response.
I following I'm making a conditional request for the same resource using If-Modified-Since. And I get a response with status code 304 No modified (btw it does not even checks the server). Without a response body. Which is fine, but I would like to access the cached body, since if its not updated I want to use that.
The question is:
Is there a convenient way to access the cached response from the first call?
(Using org.apache.httpcomponents:httpclient, org.apache.httpcomponents:httpclient-cache; version 4.5.2)
server side:
#RequestMapping("/number")
public int getNumber(HttpServletResponse response, HttpServletRequest request) {
log.info("Number gen called");
response.setHeader("Cache-Control", "max-age=" + 5);
return random.nextInt();
}
client side:
HttpGet httpget = new HttpGet("http://localhost:8080/number");
httpget.setHeader("If-Modified-Since", java.time.format.DateTimeFormatter.RFC_1123_DATE_TIME.
format(ZonedDateTime.now(ZoneId.of("GMT")).minusSeconds(1)));
HttpResponse resp = httpClient.execute(httpget);
log.info("code: " + resp.getStatusLine().getStatusCode());
// here fails because no body on 2. call
String responseString = new BasicResponseHandler().handleResponse(resp);
Http Client Init
#Bean
public HttpClient httpClient() {
return CachingHttpClients.createMemoryBound();
}
Ok so if I configure the cache explicitly, I can use that cache object directly too, so this was a typical RTFM problem, my bad.
#Bean
public HttpCacheStorage httpCacheStorage() {
CacheConfig cacheConfig = CacheConfig.custom()
.setMaxCacheEntries(1000)
.setMaxObjectSize(8192)
.build();
HttpCacheStorage cacheStorage = new BasicHttpCacheStorage(cacheConfig);
return cacheStorage;
}

Resources