001package io.freefair.spring.okhttp; 002 003import okhttp3.*; 004import org.springframework.beans.factory.ObjectProvider; 005import org.springframework.beans.factory.annotation.Autowired; 006import org.springframework.boot.autoconfigure.AutoConfigureAfter; 007import org.springframework.boot.autoconfigure.AutoConfigureBefore; 008import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; 009import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; 010import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 011import org.springframework.boot.context.properties.EnableConfigurationProperties; 012import org.springframework.context.annotation.Bean; 013import org.springframework.context.annotation.Configuration; 014import org.springframework.http.client.OkHttp3ClientHttpRequestFactory; 015 016import java.io.File; 017import java.io.IOException; 018import java.nio.file.Files; 019import java.time.Duration; 020import java.util.concurrent.TimeUnit; 021 022/** 023 * @author Lars Grefer 024 */ 025@Configuration(proxyBeanMethods = false) 026@ConditionalOnClass(OkHttpClient.class) 027@EnableConfigurationProperties(OkHttpProperties.class) 028public class OkHttp3AutoConfiguration { 029 030 @Autowired 031 private OkHttpProperties okHttpProperties; 032 033 @Autowired 034 private ObjectProvider<Configurer<OkHttpClient.Builder>> configurers; 035 036 @Autowired 037 @ApplicationInterceptor 038 private ObjectProvider<Interceptor> applicationInterceptors; 039 040 @Autowired 041 @NetworkInterceptor 042 private ObjectProvider<Interceptor> networkInterceptors; 043 044 @Bean 045 @ConditionalOnMissingBean 046 public OkHttpClient okHttp3Client( 047 ObjectProvider<Cache> cache, 048 ObjectProvider<CookieJar> cookieJar, 049 ObjectProvider<Dns> dns, 050 ConnectionPool connectionPool 051 ) { 052 OkHttpClient.Builder builder = new OkHttpClient.Builder(); 053 054 cache.ifUnique(builder::cache); 055 056 builder.connectTimeout(okHttpProperties.getConnectTimeout().toMillis(), TimeUnit.MILLISECONDS); 057 builder.readTimeout(okHttpProperties.getReadTimeout().toMillis(), TimeUnit.MILLISECONDS); 058 builder.writeTimeout(okHttpProperties.getWriteTimeout().toMillis(), TimeUnit.MILLISECONDS); 059 builder.pingInterval(okHttpProperties.getPingInterval().toMillis(), TimeUnit.MILLISECONDS); 060 061 cookieJar.ifUnique(builder::cookieJar); 062 063 dns.ifUnique(builder::dns); 064 065 builder.connectionPool(connectionPool); 066 067 builder.followRedirects(okHttpProperties.isFollowRedirects()); 068 builder.followSslRedirects(okHttpProperties.isFollowSslRedirects()); 069 builder.retryOnConnectionFailure(okHttpProperties.isRetryOnConnectionFailure()); 070 071 applicationInterceptors.forEach(i -> builder.interceptors().add(i)); 072 073 networkInterceptors.forEach(i -> builder.networkInterceptors().add(i)); 074 075 configurers.forEach(configurer -> configurer.configure(builder)); 076 077 return builder.build(); 078 } 079 080 @Bean 081 @ConditionalOnMissingBean 082 public ConnectionPool okHttp3ConnectionPool() { 083 int maxIdleConnections = okHttpProperties.getConnectionPool().getMaxIdleConnections(); 084 Duration keepAliveDuration = okHttpProperties.getConnectionPool().getKeepAliveDuration(); 085 return new ConnectionPool(maxIdleConnections, keepAliveDuration.toNanos(), TimeUnit.NANOSECONDS); 086 } 087 088 @Bean 089 @ConditionalOnMissingBean 090 @ConditionalOnProperty(value = "okhttp.cache.enabled", havingValue = "true", matchIfMissing = true) 091 public Cache okHttp3Cache() throws IOException { 092 File directory = okHttpProperties.getCache().getDirectory(); 093 if (directory == null) { 094 directory = Files.createTempDirectory("okhttp-cache").toFile(); 095 } 096 return new Cache(directory, okHttpProperties.getCache().getMaxSize().toBytes()); 097 } 098 099 /** 100 * @author Lars Grefer 101 */ 102 @Configuration(proxyBeanMethods = false) 103 @ConditionalOnClass(OkHttp3ClientHttpRequestFactory.class) 104 @AutoConfigureBefore(OkHttpRestTemplateAutoConfiguration.class) 105 @AutoConfigureAfter(OkHttp3AutoConfiguration.class) 106 public static class RequestFactoryAutoConfiguration { 107 108 @Bean 109 @ConditionalOnMissingBean(OkHttp3ClientHttpRequestFactory.class) 110 public OkHttp3ClientHttpRequestFactory okHttp3ClientHttpRequestFactory(OkHttpClient okHttpClient) { 111 return new OkHttp3ClientHttpRequestFactory(okHttpClient); 112 } 113 } 114}