带有参数的 Spring RestTemplate HTTP Post 导致 400 错误请求错误

2022-09-01 20:58:21

可能的重复 需要帮助 RestTemplate Post Request with Body Parameters?Spring RESTtemplate POST 但这些答案对我
不起作用,我试图从 Spring Android 的 API 获取访问令牌。来自Instagram文档的请求是这样的: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进行了测试,它工作正常。


答案 1

如果请求不接受内容类型,则服务器通常会返回 HTTP 400。来自 instagram 的 curl 示例使用指定多部分帖子数据的参数:-F

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

因此,您可能需要尝试在 RestTemplate 请求中显式设置内容类型 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();

如前所述,像fiddler这样的代理工具对于调试非常有用。这种情况的挑战在于您正在使用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);

并将您的响应转换为字符串。您可以使用:

EntityUtils.toString(response.getEntity());

我想你想为任何对象发送一个帖子请求。为此,使用DefaultHttpClient。HttpPost 对象将 url 作为参数(只有 url 而不是参数)。要发送的参数可以在上面的 BasicNameValuePair 对象中进行编辑。第一个参数作为参数的名称,第二个参数是其值。一旦您调用了 execute 方法,响应就会出现在 HttpResponse 对象中。现在,您必须将 HttpResponse 对象转换为实体。从Entity中,您可以调用EntityUtils.toString()方法转换为String。我想你期待一个json数据。您可能必须映射与其对应的类,才能将 json 数据转换为 java 类对象。


推荐