【问题标题】:Follow 302 redirect using Spring restTemplate?使用 Spring restTemplate 遵循 302 重定向?
【发布时间】:2015-06-07 17:46:21
【问题描述】:
  RestTemplate restTemplate = new RestTemplate();

  final MappingJackson2XmlHttpMessageConverter converter = new MappingJackson2XmlHttpMessageConverter();
  final List<MediaType> supportedMediaTypes = new LinkedList<MediaType>(converter.getSupportedMediaTypes());
  supportedMediaTypes.add(MediaType.ALL);
  converter.setSupportedMediaTypes(supportedMediaTypes);
  restTemplate.getMessageConverters().add(converter);  


  ResponseEntity<MyDTO[]> response = restTemplate.getForEntity(urlBase, MyDTO[].class);

  HttpHeaders headers = response.getHeaders();
  URI location = headers.getLocation(); // Has my redirect URI

  response.getBody(); //Always null

我的印象是会自动遵循 302。我在这个假设中不正确吗?我现在需要选择这个位置并重新申请吗?

【问题讨论】:

  • 你找到答案了吗

标签: java spring redirect resttemplate


【解决方案1】:

使用默认的 ClientHttpRequestFactory 实现 - 即 SimpleClientHttpRequestFactory - 默认行为是遵循位置标头的 URL(对于带有状态代码 3xx 的响应) - 但前提是初始请求是 @ 987654324@request.

可以在这个类中找到详细信息-搜索以下方法:

protected void prepareConnection(HttpURLConnection connection, String httpMethod) throws IOException {

    ...

    if ("GET".equals(httpMethod)) {
        connection.setInstanceFollowRedirects(true);
    }

这里是HttpURLConnection.setInstanceFollowRedirects方法的相关文档注释:

设置 HTTP 重定向(响应代码为 3xx 的请求)是否应该 自动跟随此 {@code HttpURLConnection} 实例。

默认值来自followRedirects,默认为true。

【讨论】:

  • 如果我使用的是 getForEntity,它将被假定为 GET 请求。我继续并确保在 restTemplate 中使用 SimpleClientHttpRequestFactory,但结果相同。将进入您突出显示的代码并查看发生了什么。
  • 因为您的响应包含 location 标头 - 它告诉您重定向没有发生。否则,响应将包含收到的最后一个响应的结果。唯一可能是响应状态不是3xx - 位置标头被忽略。先查看响应状态码(response.getStatusCode())。
  • 我做了new RestTemplate(new SimpleClientHttpRequestFactory() { protected void prepareConnection(HttpURLConnection connection, String httpMethod) throws IOException { super.prepareConnection(connection, httpMethod); connection.setInstanceFollowRedirects(false); } }); 来禁用重定向
  • 它只遵循一个重定向
【解决方案2】:

当使用CommonsClientHttpRequestFactory(在下面使用HttpClient v3)时,您可以覆盖postProcessCommonsHttpMethod 方法并设置为跟随重定向。

public class FollowRedirectsCommonsClientHttpRequestFactory extends CommonsClientHttpRequestFactory {

  @Override
  protected void postProcessCommonsHttpMethod(HttpMethodBase httpMethod) {
    httpMethod.setFollowRedirects(true);
  }
}

然后您可以像这样使用它(带有可选的,可能预配置的 HttpClient 实例),请求将遵循 location 标头作为响应:

RestTemplate restTemplate = new RestTemplate(
      new FollowRedirectsCommonsClientHttpRequestFactory());

【讨论】:

    【解决方案3】:

    您是否尝试从一种协议重定向到另一种协议,例如从 http 到 https 或反之亦然?如果是这样,自动重定向将不起作用。看到这条评论:URLConnection Doesn't Follow Redirect

    经过Java Networking工程师的讨论,感觉我们 不应自动遵循从一种协议到另一种协议的重定向, 例如,从 http 到 https,反之亦然,这样做可能有 严重的安全后果

    来自https://bugs.java.com/bugdatabase/view_bug.do?bug_id=4620571

    否则,如果您调试RestTemplate 代码,您将看到默认情况下HttpURLConnectiongetInstanceFollowRedirects() == true 正确设置。

    【讨论】:

      【解决方案4】:

      尝试像这样创建 RestTemplate(Spring 配置):

      @Bean("smartRestTemplate")
      public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder) {
          return restTemplateBuilder
                  .setConnectTimeout(Duration.ofSeconds(..))
                  .setReadTimeout(Duration.ofSeconds(..))
                  .build();
      }
      

      【讨论】:

      • 通过解释为什么这可能在其他方法不起作用的情况下有效,这个答案会得到很大改善。
      • 它对我有帮助。但我也很感谢您的解释。
      猜你喜欢
      • 2015-11-30
      • 2019-05-10
      • 2013-09-11
      • 2013-08-15
      • 1970-01-01
      • 1970-01-01
      • 2015-07-09
      • 1970-01-01
      相关资源
      最近更新 更多