Primavera RestTemplate HTTP Post com parâmetros causam 400 ruim erro pedido

? R4j @ | Original: StackOverFlow
---

possível duplicado http://stackoverflow.com/questions/12202729/need-help-on-resttemplate-post-request-with-body-parameters e http://stackoverflow.com/questions/20557326/spring-resttemplate-post mas essas respostas não funcionam para mim Tentei obter o token de acesso de Instagram API pela Spring Android . O pedido de http://instagram.com/developer/authentication/ como este:

curl -F 'client_id=CLIENT-ID' 
-F 'client_secret=CLIENT-SECRET' 
-F 'grant_type=authorization_code' 
-F 'redirect_uri=YOUR-REDIRECT-URI' 
-F 'code=CODE' https://api.instagram.com/oauth/access_token

Aqui está o meu token de acesso solicitação ( Depois que eu começar token de solicitação de sucesso ):

 MultiValueMap<String, String> mvm = new LinkedMultiValueMap<String, String>();
    mvm.add("client_id", INSTAGRAM_CILENT_ID);
    mvm.add("client_secret", INSTAGRAM_SECRET);
    mvm.add("grant_type", "authorization_code");
    mvm.add("redirect_uri", CALLBACKURL);
    mvm.add("code", requestToken);

    InstagramResult result = restTemplate .postForObject("https://api.instagram.com/oauth/access_token", mvm, InstagramResult .class);

A classe de mapeamento resultado:

public class InstagramLogin {
   public String access_token;
   public InstagramUser user;
}

public class InstagramUser {
   public String id;
   public String username;
   public String full_name;
   public String profile_picture;
}

E o modelo de descanso :

   RestTemplate restTemplate = new RestTemplate();
    final List<HttpMessageConverter<?>> listHttpMessageConverters = new ArrayList< HttpMessageConverter<?> >(); 

    listHttpMessageConverters.add(new GsonHttpMessageConverter());
    listHttpMessageConverters.add(new FormHttpMessageConverter());
    listHttpMessageConverters.add(new StringHttpMessageConverter());
    restTemplate.setMessageConverters(listHttpMessageConverters);

Mas eu sempre obter 400 ruim erro pedido. Aqui está o meu rastreamento de pilha :

04-03 09:32:45.366: W/RestTemplate(31709): POST request for "https://api.instagram.com/oauth/access_token" resulted in 400 (BAD REQUEST); invoking error handler
04-03 09:32:46.857: E//DefaultRequestRunner.java:138(31709): 09:32:46.862 Thread-32787 An exception occurred during request network execution :400 BAD REQUEST
04-03 09:32:46.857: E//DefaultRequestRunner.java:138(31709): org.springframework.web.client.HttpClientErrorException: 400 BAD REQUEST
04-03 09:32:46.857: E//DefaultRequestRunner.java:138(31709):    at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:76)
04-03 09:32:46.857: E//DefaultRequestRunner.java:138(31709):    at org.springframework.web.client.RestTemplate.handleResponseError(RestTemplate.java:524)
04-03 09:32:46.857: E//DefaultRequestRunner.java:138(31709):    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:481)
04-03 09:32:46.857: E//DefaultRequestRunner.java:138(31709):    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:439)
04-03 09:32:46.857: E//DefaultRequestRunner.java:138(31709):    at org.springframework.web.client.RestTemplate.postForObject(RestTemplate.java:317)

P / s : Estou certamente os meus valores de parâmetros está certo, porque eu testei por onda e funcionou muito bem .

---

Top 5 Responder

1Roy Clarkson @

Um servidor, muitas vezes, retornar um HTTP 400 se o tipo de conteúdo não é aceitável para um pedido . O exemplo a onda de instagram usa o parâmetro -F, que especifica dados multipart post:

-F, --form CONTENT  Specify HTTP multipart POST data (H)

Portanto, você pode querer tentar definir o cabeçalho HTTP Content-type no seu pedido RestTemplate explicitamente :

HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);
HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<MultiValueMap<String, String>>(mvm, requestHeaders);
ResponseEntity<InstagramResult> response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, InstagramResult.class);
InstagramResult result = response.getBody();

Como mencionado anteriormente nos comentários, uma ferramenta de proxy como violinista pode ser realmente útil para a depuração . O desafio com esta situação é que você está trabalhando com SSL, portanto, essas ferramentas não será capaz de "ver" as comunicações criptografadas sem configuração especial.

2Aarambh @
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(LINKEDIN_POST_URL);

List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("grant_type", grant_type));
nameValuePairs.add(new BasicNameValuePair("code", code));
nameValuePairs.add(new BasicNameValuePair("redirect_uri", redirect_uri);
nameValuePairs.add(new BasicNameValuePair("client_id", client_id));
nameValuePairs.add(new BasicNameValuePair("client_secret", client_secret));

httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httppost);

E para converter sua resposta à cadeia. Você pode usar :

EntityUtils.toString(response.getEntity());

Eu suponho que você quer enviar uma solicitação post para qualquer objeto . Para que um DefaultHttpClient é usado . HttpPost objeto assumirá a url como argumento (apenas url não os parâmetros ) . Os parâmetros que você deseja enviar podem ser editados anteriormente em BasicNameValuePair objeto. O primeiro parâmetro como o nome do parâmetro e segunda seria o seu valor . Assim que você chamar o método execute a resposta virá no objeto HttpResponse . Você agora tem que converter o objeto HttpResponse a Entidade. E a partir de Entidade você pode chamar o método EntityUtils.toString () para converter a cadeia. Eu suponho que você está esperando um dado JSON. Você pode ter que mapear uma classe correspondente a ele para converter dados JSON para classe java objeto.