【问题标题】:Resttemplate GET Request with Custom Headers带有自定义标头的 Resttemplate GET 请求
【发布时间】:2016-11-12 03:54:25
【问题描述】:

我需要发送一个带有标题的 GET 请求:Content-Type: application/camiant-msr-v2.0+xml。我期待来自服务器的 XML 响应。我用 Postman 测试了请求和响应,一切都很好。但是当我尝试在 Spring 中使用 RestTemplate 执行此操作时,我总是收到 400 错误请求。 spring 的例外情况是:

Jul 09, 2016 12:53:38 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [dispatcherServlet] in context with path [/smp] threw exception [Request processing failed; nested exception is org.springframework.web.client.HttpClientErrorException: 400 Bad Request] with root cause
org.springframework.web.client.HttpClientErrorException: 400 Bad Request
    at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:91)
    at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:641)
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:597)
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:557)
    at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:475)

我的代码:

MultiValueMap<String, String> headers = new LinkedMultiValueMap<String, String>();
headers.add("Content-Type", "application/camiant-msr-v2.0+xml");

HttpEntity<?> entity = new HttpEntity<Object>(headers);
log.debug("request headers: " + entity.getHeaders());
ResponseEntity<String> response = restTemplate.exchange(queryUrl, HttpMethod.GET, entity, String.class);

调试消息将标头显示为{Content-Type=[application/camiant-msr-v2.0+xml]},这似乎是正确的。我想知道我的请求出了什么问题,是否有办法查看在线上的请求以进行调试。

【问题讨论】:

  • 如果您要发送 GET,为什么要提供 Content-Type 标头?你希望它改为Accept 吗?
  • @nicholas.hauschild 因为服务器期望,只有提供该标头,我才能获得 XML 响应。
  • @nicholas.hauschild 我有点理解你的意思,但 API 规范这么说,而且 Postman 也能正常工作。
  • @nicholas.hauschild 实际上,将其更改为 Accept 对我有用!我认为这是因为 Java 库防止了不规则的使用,例如在 GET 请求中设置Content-Type。非常感谢!

标签: spring rest resttemplate custom-headers


【解决方案1】:

以下内容对我有用:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

@Service
public class Http {

    @Autowired
    private RestTemplate restTemplate;

    public String doGet(final String url) throws Exception {
        MultiValueMap<String, String> headers = new LinkedMultiValueMap<String, String>();
        headers.add(HttpHeaders.USER_AGENT, "Mozilla/5.0");
        headers.add(HttpHeaders.ACCEPT_LANGUAGE, "en-US,en;q=0.8");
        HttpEntity<?> entity = new HttpEntity<Object>(headers);
        HttpEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, entity, String.class);
        return response.getBody();
    }

}

【讨论】:

    【解决方案2】:

    实际上要传递的标头应该命名为Accept而不是Content-Type,因为它是一个GET方法。但是服务器 API 文档不知何故说它需要 Content-Type,并且来自命令行/Postman 的 API 在 Content-TypeAccept 上运行良好。我认为是 Java 库阻止了 Content-Type 标头传递给 GET 请求。

    【讨论】:

      【解决方案3】:

      400 的可能解释是请求的内容类型不可接受或 url 不匹配。

      从我个人的经验来看,我有一种强烈的感觉,你正在搞砸 queryUrl 所以在这里微调我建议你使用 Spring 的 UriComponentsBuilder 类。

      UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url)
              .queryParam("data", data);
      
      HttpEntity<?> entity = new HttpEntity<>(headers);
      
      HttpEntity<String> response = restTemplate.exchange(
              builder.build().encode().toUri(), 
              HttpMethod.GET, 
              entity, 
              String.class);
      

      如果它仍然不起作用,请告诉我。

      【讨论】:

      • 非常感谢您的回复。但是您的方法仍然出现错误的请求错误。我打印出来的url,和我在Postman中用的一模一样,效果很好。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-01
      • 2012-05-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多