4

I have a request that is working fine when I try to send through postman. I was trying to implement the same using code where I faced an error.

The code i am using -

RestTemplate restTemplate = new RestTemplate();    
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

MultiValueMap<String, String> map= new LinkedMultiValueMap<String, String>();
map.add("client_id", clientid);
map.add("client_secret",clientsecret);

HttpEntity<?> request = new HttpEntity<>(map, headers);
logger.info(request.toString());

UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(access_token_url)
                    .queryParam("grant_type", "client_credentials");

logger.info("URI -" + builder.toUriString());

ResponseEntity<String> response = restTemplate.exchange(builder.build().encode().toUri(), 
   HttpMethod.GET, request, String.class);
logger.info("Response" + response.getBody());

The error I am getting is -

org.springframework.web.client.HttpClientErrorException$Unauthorized: 401 Unauthorized

But the same works in POSTMAN with the same details.

Something I want to specify

  • The back-end API is not in my hands.
  • The clientid, clientsecret, access_token_url are fetched from properties file and are correct I have cross checked them.
  • It is a GET request with x-www-form-urlencoded data. I checked it multiple times it is not POST
  • There is no Authorization such as Basic Auth as it is not set in POSTMAN itself
  • Went through This This and This nothing helped.

My main concern is I have never seen anywhere sending a GET request with method body, but it is working in POSTMAN and if it is working there why not in the code? Where I am going wrong?

EDIT - 1 Was marked duplicate with This but its a different error code overall. The OP got 500 Internal Server Error as he was giving wrong content type.

EDIT - 2 DEBUG Output-

2019-07-31 14:53:05.208 DEBUG 3576 --- [nio-8080-exec-1] o.s.web.client.RestTemplate              : HTTP GET ORIGINAL_URL?grant_type=client_credentials
2019-07-31 14:53:05.215 DEBUG 3576 --- [nio-8080-exec-1] o.s.web.client.RestTemplate              : Accept=[text/plain, application/json, application/*+json, */*]
2019-07-31 14:53:05.218 DEBUG 3576 --- [nio-8080-exec-1] o.s.web.client.RestTemplate              : Writing [{client_id=[CLIENTID], client_secret=[CLIENT_SECRET]}] as "application/x-www-form-urlencoded"
2019-07-31 14:53:06.976 DEBUG 3576 --- [nio-8080-exec-1] o.s.web.client.RestTemplate              : Response 401 UNAUTHORIZED
2019-07-31 14:53:07.034 DEBUG 3576 --- [nio-8080-exec-1] m.m.a.RequestResponseBodyMethodProcessor : Using 'text/html', given [text/html, application/xhtml+xml, image/webp, image/apng, application/signed-exchange;v=b3, application/xml;q=0.9, */*;q=0.8] and supported [text/plain, */*, text/plain, */*, application/json, application/*+json, application/json, application/*+json]
2019-07-31 14:53:07.035 DEBUG 3576 --- [nio-8080-exec-1] m.m.a.RequestResponseBodyMethodProcessor : Nothing to write: null body
2019-07-31 14:53:07.039 DEBUG 3576 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed 200 OK
2019-07-31 14:53:07.108 DEBUG 3576 --- [io-8080-exec-10] o.s.web.servlet.DispatcherServlet        : GET "/favicon.ico", parameters={}
2019-07-31 14:53:07.119 DEBUG 3576 --- [io-8080-exec-10] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped to ResourceHttpRequestHandler [class path resource [META-INF/resources/], class path resource [resources/], class path resource [static/], class path resource [public/], ServletContext resource [/], class path resource []]
2019-07-31 14:53:07.181 DEBUG 3576 --- [io-8080-exec-10] o.s.web.servlet.DispatcherServlet        : Completed 200 OK
Parth Manaktala
  • 1,112
  • 9
  • 27
  • Possible duplicate of [REST POST works correctly with POSTMAN but exception when using Spring RestTemplate](https://stackoverflow.com/questions/37339753/rest-post-works-correctly-with-postman-but-exception-when-using-spring-resttempl) – Mebin Joe Jul 31 '19 at 07:15
  • Have you logged the spring request to see if it matches your postman request? There is some usefull class like https://stackoverflow.com/questions/7952154/spring-resttemplate-how-to-enable-full-debugging-logging-of-requests-responses#33009822 – Benjamin Caure Jul 31 '19 at 07:17
  • 1
    can you show the postman curl for your request? – jpganz18 Jul 31 '19 at 07:20
  • You are telling us one way works another doesn’t. You post the code for the one that doesn’t but you don’t post the call that works. Are we supposed to guess what your API looks like so we can fix your broken code? – Toerktumlare Jul 31 '19 at 07:45
  • Here is the curl that is wokring `curl -X GET \ 'URL-OF-CLIENT?grant_type=client_credentials' \ -H 'Content-Type: application/x-www-form-urlencoded' \ -d 'client_secret=SECRET&client_id=ID'` – Parth Manaktala Jul 31 '19 at 08:06
  • check if you have a client certificate configured in postman settigns – e.g78 Jul 31 '19 at 08:22
  • It is not @e.g78 – Parth Manaktala Jul 31 '19 at 08:23
  • export the postman collection as json and paste it, otherwise it is impossible to compare it with the resttemplate request – e.g78 Jul 31 '19 at 08:26
  • @e.g78 the postman is not with me. I cannot access it directly. But i can assure that everything in request template is as per the postman. Including all headers and predefined parameters, there is no typos or anything missing. – Parth Manaktala Jul 31 '19 at 09:20

3 Answers3

4

for the same use case, we are using the below implementation.

RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
headers.set("Accept", MediaType.APPLICATION_JSON_VALUE);
String token = new String(Base64.getEncoder().encode((clientId + ":" + clientSecret).getBytes()));
headers.add("Authorization", "Basic " + token);
HttpEntity<?> request = new HttpEntity<>(headers);
logger.info(request.toString());
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(access_token_url).queryParam("grant_type", "client_credentials");
logger.info("URI -" + builder.toUriString());
ResponseEntity<String> response = restTemplate.exchange(builder.build().encode().toUri(), HttpMethod.POST,request, String.class);
logger.info("Response" + response.getBody());

this might help you.

Eeshwar Ankathi
  • 260
  • 3
  • 11
0

i suspect the following. You are double encoding your url, change:

restTemplate.exchange(builder.build().encode().toUri(), 
    HttpMethod.GET, request, String.class);

to

restTemplate.exchange(builder.build().toUri(), 
    HttpMethod.GET, request, String.class);

You can easy match your requests by enabling debug for spring web.

application.properties

logging.level.org.springframework.web: DEBUG
Toerktumlare
  • 12,548
  • 3
  • 35
  • 54
0

I had a very similar issue. The problem turned out to be that there was a proxy required to access a URI outside the company. Postman had been configured to use the proxy.

Here's the code to fix this:

import java.net.InetSocketAddress;
import java.net.Proxy;
import org.springframework.http.client.SimpleClientHttpRequestFactory;

// Initialize the REST Template with a proxy.
private RestTemplate getRestTemplate(){
    if(restTemplate==null) {
        Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort));
        SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
        requestFactory.setProxy(proxy);
        restTemplate = new RestTemplate(requestFactory);
    }
    return restTemplate;
}

See // https://www.baeldung.com/java-resttemplate-proxy

Joel
  • 572
  • 5
  • 18