web-dev-qa-db-ja.com

パラメーター付きのSpring RestTemplate HTTP Postにより400の不正な要求エラーが発生する

可能性のある重複 ボディパラメータを使用したRestTemplateポストリクエストのヘルプが必要ですか? および Spring RESTtemplate POST しかし、これらの回答は私には機能しません
Spring AndroidでInstagram AP​​Iからアクセストークンを取得しようとしました。 Instagramのドキュメント からのリクエストは次のようになります。

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

リクエストアクセストークンは次のとおりです(リクエストトークンを取得した後):

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

結果マッピングクラス:

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

そして残りのテンプレート:

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

しかし、私は常に400の悪いリクエストエラーを受け取ります。これが私のスタックトレースです。

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:curlでテストし、正常に機能したため、パラメータ値が正しいことは確かです。

21
R4j

コンテンツタイプがリクエストに受け入れられない場合、サーバーはしばしばHTTP 400を返します。 instagramのcurlの例では、-Fパラメータは、マルチパート投稿データを指定します:

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

したがって、RestTemplateリクエストでContent-type HTTPヘッダーを明示的に設定してみてください。

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

コメントで前述したように、フィドラーのようなプロキシツールはデバッグに非常に役立ちます。この状況での課題は、SSLで作業しているため、これらのツールは特別な構成なしでは暗号化された通信を「見る」ことができないことです。

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

そして、応答を文字列に変換します。次を使用できます。

EntityUtils.toString(response.getEntity());

任意のオブジェクトの投稿リクエストを送信するとします。そのためにDefaultHttpClientが使用されます。 HttpPostオブジェクトは引数としてurlを取ります(パラメーターではなくurlのみ)。送信するパラメーターは、上記のBasicNameValuePairオブジェクトで編集できます。パラメーターの名前としての最初のパラメーターと2番目のパラメーター。 executeメソッドを呼び出すとすぐに、HttpResponseオブジェクトに応答が返されます。ここで、HttpResponseオブジェクトをEntityに変換する必要があります。また、EntityからEntityUtils.toString()メソッドを呼び出してStringに変換できます。 JSONデータを期待していると思います。 JSONデータをJavaクラスオブジェクトに変換するには、それに対応するクラスをマッピングする必要がある場合があります。

1
Aarambh