Spring RestTemplate HTTP Post с параметрами вызывает ошибку 400 ошибок
Возможный дубликат Нужна помощь по запросу PostTemplate с параметрами тела? и Spring RESTtemplate POST, но эти ответы не работают для меня
Я попытался получить токен доступа из Instagram
API Spring Android. Запрос Instagram document следующим образом:
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: Я уверен, что мои значения параметров правильные, потому что я проверял завиток и работал нормально.
Ответы
Ответ 1
Сервер часто возвращает HTTP 400, если тип контента неприемлем для запроса. Пример скручивания из instagram использует параметр -F
, который задает многостраничные данные:
-F, --form CONTENT Specify HTTP multipart POST data (H)
Следовательно, вы можете попробовать явно настроить HTTP-заголовок Content-type в запросе 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();
Как упоминалось ранее в комментариях, прокси-инструмент, такой как скрипач, может быть действительно полезен для отладки. Проблема с этой ситуацией заключается в том, что вы работаете с SSL, поэтому эти инструменты не смогут "видеть" зашифрованные сообщения без специальной настройки.
Ответ 2
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);
И для преобразования вашего ответа в String. Вы можете использовать:
EntityUtils.toString(response.getEntity());
Предположим, вы хотите отправить запрос на отправку для любого объекта. Для этого используется DefaultHttpClient.
Объект HttpPost возьмет url как аргумент (только url не параметры).
Параметры, которые вы хотите отправить, можно редактировать выше в объекте BasicNameValuePair. Первым параметром является имя параметра и второе значение.
Как только вы вызовете метод execute, ответ появится в объекте HttpResponse.
Теперь вам нужно преобразовать объект HttpResponse в Entity. А из Entity вы можете вызвать метод EntityUtils.toString() для преобразования в String. Я предполагаю, что вы ожидаете данные json. Возможно, вам придется сопоставить соответствующий ему класс, чтобы преобразовать данные json в объект класса java.