使用 Spring RestTemplate 遵循 302 重定向?

问题描述 投票:0回答:5
  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
5个回答
26
投票

使用默认的

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

详情可以在这个类中找到——搜索以下方法:

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

    ...

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

这里是

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

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

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


11
投票

您是否尝试从一种协议重定向到另一种协议,例如从 http 到 https 或者反之亦然?如果是这样,自动重定向将不起作用。请参阅此评论:URLConnection 不遵循重定向

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

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

否则,如果您调试

RestTemplate
代码,您将看到默认情况下
HttpURLConnection
已通过
getInstanceFollowRedirects() == true
正确设置。


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

0
投票

如果

RestTemplate
是 Spring Bean 并且由
RestTemplateBuilder
创建:

    @Bean
    public RestTemplate restTemplate(RestTemplateBuilder builder) {
        final var timeout = Duration.ofSeconds(5);
        return builder
                .requestFactory(() -> new SimpleClientHttpRequestFactory() {
                    @Override
                    protected void prepareConnection(HttpURLConnection connection,
                                                     String httpMethod) throws IOException {
                        super.prepareConnection(connection, httpMethod);
                        // always follow redirect for any request method
                        connection.setInstanceFollowRedirects(true);
                    }
                })
                .setConnectTimeout(timeout)
                .setReadTimeout(timeout)
                .build();
    }

-5
投票

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

@Bean("smartRestTemplate")
public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder) {
    return restTemplateBuilder
            .setConnectTimeout(Duration.ofSeconds(..))
            .setReadTimeout(Duration.ofSeconds(..))
            .build();
}
© www.soinside.com 2019 - 2024. All rights reserved.