web-dev-qa-db-fra.com

La publication HTTP Spring RestTemplate avec des paramètres provoque une erreur de requête incorrecte 400

Double possible Besoin d'aide pour RestTemplate Post Request avec des paramètres de corps? et Spring RESTtemplate POST mais ces réponses ne fonctionnent pas pour moi
J'ai essayé d'obtenir un jeton d'accès à partir de l'API Instagram de Spring Android. La demande de le document de Instagram comme ceci:

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

Voici le jeton d'accès à ma demande (une fois le jeton de demande validé):

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

La classe de mappage des résultats:

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

Et le gabarit de repos:

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

Mais je reçois toujours 400 mauvaise erreur de requête. Voici ma trace de pile:

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: je suis sûrement mes valeurs de paramètre sont correctes, parce que j'ai testé par curl et cela a bien fonctionné.

20
R4j

Un serveur renvoie souvent un HTTP 400 si le type de contenu n'est pas acceptable pour une requête. L'exemple de curl d'instagram utilise le paramètre -F qui spécifie des données de publication en plusieurs parties:

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

Par conséquent, vous voudrez peut-être essayer de définir explicitement l'en-tête HTTP Content-type dans votre demande RestTemplate:

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

Comme mentionné précédemment dans les commentaires, un outil proxy tel que fiddler peut être très utile pour le débogage. Le problème avec cette situation est que vous travaillez avec SSL, ces outils ne pourront donc pas "voir" les communications cryptées sans configuration spéciale. 

27
Roy Clarkson
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);

Et pour convertir votre réponse en String. Vous pouvez utiliser:

EntityUtils.toString(response.getEntity());

Je suppose que vous voulez envoyer une demande de publication pour n’importe quel objet. Pour cela, un DefaultHttpClient est utilisé . L'objet HttpPost prendra l'URL comme argument (uniquement l'URL et pas les paramètres) . Les paramètres que vous souhaitez envoyer peuvent être modifiés ci-dessus dans l'objet BasicNameValuePair. Le premier paramètre comme nom du paramètre et le second correspond à sa valeur . Dès que vous appelez la méthode execute, la réponse viendra dans l'objet HttpResponse . Vous devez maintenant convertir l'objet HttpResponse en entité. Et depuis Entity, vous pouvez appeler la méthode EntityUtils.toString () pour convertir en String. Je suppose que vous attendez une donnée JSON. Vous devrez peut-être mapper une classe correspondante pour convertir les données JSON en objet de classe Java.

1
Aarambh