001package io.freefair.spring.okhttp.autoconfigure; 002 003import io.freefair.spring.okhttp.client.OkHttpClientRequestFactory; 004import okhttp3.OkHttpClient; 005import org.springframework.boot.autoconfigure.AutoConfiguration; 006import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; 007import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; 008import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration; 009import org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration; 010import org.springframework.boot.autoconfigure.web.client.RestTemplateBuilderConfigurer; 011import org.springframework.boot.ssl.SslBundle; 012import org.springframework.boot.web.client.ClientHttpRequestFactorySettings; 013import org.springframework.boot.web.client.RestTemplateBuilder; 014import org.springframework.boot.web.client.RestTemplateCustomizer; 015import org.springframework.context.annotation.Bean; 016import org.springframework.context.annotation.Conditional; 017import org.springframework.context.annotation.Lazy; 018import org.springframework.http.client.ClientHttpRequestFactory; 019import org.springframework.util.Assert; 020import org.springframework.web.client.RestTemplate; 021import javax.net.ssl.SSLContext; 022import javax.net.ssl.SSLSocketFactory; 023import javax.net.ssl.TrustManager; 024import javax.net.ssl.X509TrustManager; 025import java.time.Duration; 026import java.util.function.Function; 027 028/** 029 * @author Lars Grefer 030 * @see RestTemplateAutoConfiguration 031 */ 032@AutoConfiguration(before = RestTemplateAutoConfiguration.class, after = HttpMessageConvertersAutoConfiguration.class) 033@ConditionalOnClass({RestTemplateCustomizer.class, RestTemplate.class, OkHttpClientRequestFactory.class}) 034@Conditional(NotReactiveWebApplicationCondition.class) 035public class OkHttpRestTemplateAutoConfiguration { 036 @Bean 037 @Lazy 038 @ConditionalOnMissingBean 039 public RestTemplateBuilder restTemplateBuilder(RestTemplateBuilderConfigurer restTemplateBuilderConfigurer, OkHttpClient okHttpClient) { 040 RestTemplateBuilder builder = new RestTemplateBuilder(); 041 builder = builder.requestFactory(new RequestFactoryFunction(okHttpClient)); 042 return restTemplateBuilderConfigurer.configure(builder); 043 } 044 045 046 static class RequestFactoryFunction implements Function<ClientHttpRequestFactorySettings, ClientHttpRequestFactory> { 047 private OkHttpClient okHttpClient; 048 049 @Override 050 public ClientHttpRequestFactory apply(ClientHttpRequestFactorySettings settings) { 051 OkHttpClient.Builder builder = okHttpClient.newBuilder(); 052 Duration connectTimeout = settings.connectTimeout(); 053 if (connectTimeout != null) { 054 builder.connectTimeout(connectTimeout); 055 } 056 Duration readTimeout = settings.readTimeout(); 057 if (readTimeout != null) { 058 builder.readTimeout(readTimeout); 059 } 060 SslBundle sslBundle = settings.sslBundle(); 061 if (sslBundle != null) { 062 Assert.state(!sslBundle.getOptions().isSpecified(), "SSL Options cannot be specified with OkHttp"); 063 SSLContext sslContext = sslBundle.createSslContext(); 064 SSLSocketFactory socketFactory = sslContext.getSocketFactory(); 065 TrustManager[] trustManagers = sslBundle.getManagers().getTrustManagers(); 066 Assert.state(trustManagers.length == 1, "Trust material must be provided in the SSL bundle for OkHttp3ClientHttpRequestFactory"); 067 builder.sslSocketFactory(socketFactory, (X509TrustManager) trustManagers[0]); 068 } 069 return new OkHttpClientRequestFactory(builder.build()); 070 } 071 072 public RequestFactoryFunction(final OkHttpClient okHttpClient) { 073 this.okHttpClient = okHttpClient; 074 } 075 } 076}