如何在收到HTTP重定向响应后禁用Spring RestTemplate?

5

我正在与一个古老的服务进行集成,该服务将 jsessionid 添加到URL并重定向到它。 我使用 RestTemplate 与该服务通信。

问题在于,它会一直跟随重定向,因为我没有设置 jsession cookie。

如何在Spring RestTemplate中关闭跟随重定向?


如果您需要使用Spring Security等集成功能,那么Spring RestTemplate可能是合适的选择。但是,当您需要更好地控制HTTP底层时,我建议选择另一个HTTP客户端库。 - Ondra Žižka
3个回答

12

我想出了一种方法,不知道这是否是首选方法。

@Bean
public RestTemplate restTemplate() {
    RestTemplate restTemplate = new RestTemplate();
    final HttpComponentsClientHttpRequestFactory factory = 
             new HttpComponentsClientHttpRequestFactory();
    CloseableHttpClient build = 
             HttpClientBuilder.create().disableRedirectHandling().build();
    factory.setHttpClient(build);
    restTemplate.setRequestFactory(factory);
    return restTemplate;
}

2
你可以编写自己的HttpRequestFactory类并覆盖默认行为:
class CustomClientHttpRequestFactory extends SimpleClientHttpRequestFactory {
    @Override
    protected void prepareConnection(HttpURLConnection connection, String httpMethod) throws IOException {
        super.prepareConnection(connection, httpMethod);
        connection.setInstanceFollowRedirects(false);
    }
}

@Configuration
public class AppConfig {

    @Bean
    public RestTemplate httpClient(RestTemplateBuilder builder) {
        return builder
                .setConnectTimeout(Duration.ofSeconds(10))
                .setReadTimeout(Duration.ofSeconds(10))
                .requestFactory(CustomClientHttpRequestFactory.class)
                .build();
    }

}

1

由于我发现上面的其他解决方案不适用于当前的Spring 5.x和Spring Boot 2.7,因此在此添加我的解决方案。

重要的是,Spring可以配置大约6种不同的HTTP客户端库。它们的配置方式不同,并且通过直接使用客户端库的API来完成。

以下是使用Apache HttpClient(历史上称为HttpComponents)创建测试RestTemplate的示例。语法为Kotlin。

import org.apache.http.client.HttpClient
import org.apache.http.impl.client.HttpClients
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.beans.factory.annotation.Value
import org.springframework.boot.web.client.RestTemplateBuilder
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Profile
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory
import org.springframework.web.client.RestTemplate

@Bean @Qualifier("forTests")
fun restTemplateHttpsWithTestTrustStore(builder: RestTemplateBuilder): RestTemplate {

    val httpClient: HttpClient = HttpClients.custom()
        .disableRedirectHandling()
        .build()

    return builder.requestFactory { HttpComponentsClientHttpRequestFactory(httpClient) }.build()
}

然后进行测试:

@SpringBootTest(
    webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT,
)
class HttpsWorksTest {

    @LocalServerPort private var port = 0
    @Autowired @Qualifier("forTests") private lateinit var restTemplateTrustStore: RestTemplate

    @Test
    fun httpsSelfRequestTest() {
        var url = "$proto://localhost:$port/someRediirectingEndpoint"
        log.info("Requesting: GET $url")

        var response = restTemplateTrustStore.getForEntity(url, String::class.java)
        Assertions.assertThat(response.statusCode).isEqualTo(HttpStatus.SEE_OTHER)
    }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接