Getting 400 BAD Request when using Spring RestTemplate to POST

user2498487 picture user2498487 · Jun 18, 2013 · Viewed 16.1k times · Source

Can someone please help me figure out what is wrong with the code below?

I am using Spring 3.1.1 RestTemplate to try to call a REST WS on Box.com to get a new access token from a refresh token.

The code below is returning a 400 (BAD REQUEST). I am able to successfully call the same method using the FireFox POST plugin. I've compared output from the writeForm method on the FormHttpMessageConverter class and it is exactly as I am sending it from FireFox.

Does anyone have any ideas?

public static void main(String[] args) throws InterruptedException {
    try {
        String apiUrl = "https://www.box.com/api/oauth2/token";
        String clientSecret = "[MY SECRET]";
        String clientId = "[MY ID]";
        String currentRefreshToken = "[MY CURRENT VALID REFRESHTOKEN]";

        RestTemplate restTemplate = new RestTemplate();

        List<HttpMessageConverter<?>> messageConverters = new ArrayList<HttpMessageConverter<?>>();

        messageConverters.add(new FormHttpMessageConverter());
        restTemplate.setMessageConverters(messageConverters);

        MultiValueMap<String, String> body = new LinkedMultiValueMap<String, String>();

        body.add("grant_type", "refresh_token");
        body.add("refresh_token", currentRefreshToken);
        body.add("client_id", clientId);
        body.add("client_secret", clientSecret);

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        headers.add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8,application/json");
        headers.add("Accept-Encoding", "gzip, deflate");


        HttpEntity<?> entity = new HttpEntity<Object>(body, headers);

        restTemplate.exchange(apiUrl, HttpMethod.POST, entity, String.class);
    } catch (Exception ex) {
        System.out.println("ex = " + ex.getMessage());
    }
  }
}

Answer

Dillon Ryan Redding picture Dillon Ryan Redding · Feb 25, 2015

The no-arg constructor for RestTemplate uses the java.net API to make requests, which does not support gzip encoding. There is, however, a constructor that accepts a ClientHttpRequestFactory. You can use the HttpComponentsClientHttpRequestFactory implementation, which uses the Apache HttpComponents HttpClient API to make requests. This does support gzip encoding. So you can do something like the following (from the Spring Docs) when creating your RestTemplate:

HttpClient httpClient = HttpClientBuilder.create().build();
ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
RestTemplate restTemplate = new RestTemplate(requestFactory);