Reputation: 2445
I'm integrating with an ancient service that is adds jsessionid
to the URL and redirects to it. I'm using RestTemplate
to talk to the service.
The problem is that it follows the redirect forever, since I'm not setting the jsession
cookie.
How do I turn off following the redirects in Spring RestTemplate?
Upvotes: 8
Views: 10918
Reputation: 46796
Adding my solution as I found the others above not fitting the current Spring 5.x and Spring Boot 2.7.
The important aspect is that Spring can be configured with around 6 different HTTP client libraries. The way to configure them differs, and is done by using the client lib's API directly.
Below is an example for Apache HttpClient (historically called HttpCompoments) used to create a RestTemplate
for a test. The syntax is 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()
}
And then the test:
@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)
}
}
Upvotes: 1
Reputation: 2445
I figured out one way to do it, don't know if this is the preferred way to do it.
@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;
}
Upvotes: 16
Reputation: 148
You can also write your own HttpRequestFactory class and override the default behaviour:
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();
}
}
Upvotes: 2