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.AutoConfiguration; 007import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; 008import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; 009import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 010import org.springframework.boot.context.properties.EnableConfigurationProperties; 011import org.springframework.context.annotation.Bean; 012 013import javax.net.ssl.HostnameVerifier; 014import java.io.File; 015import java.io.IOException; 016import java.nio.file.Files; 017import java.time.Duration; 018import java.util.concurrent.TimeUnit; 019 020/** 021 * @author Lars Grefer 022 */ 023@SuppressWarnings("SpringJavaAutowiredFieldsWarningInspection") 024@AutoConfiguration 025@ConditionalOnClass(OkHttpClient.class) 026@EnableConfigurationProperties(OkHttpProperties.class) 027public class OkHttp3AutoConfiguration { 028 029 @Autowired 030 private OkHttpProperties okHttpProperties; 031 032 @Autowired 033 private ObjectProvider<OkHttp3Configurer> configurers; 034 035 @Autowired 036 @ApplicationInterceptor 037 private ObjectProvider<Interceptor> applicationInterceptors; 038 039 @Autowired 040 @NetworkInterceptor 041 private ObjectProvider<Interceptor> networkInterceptors; 042 043 @Bean 044 @ConditionalOnMissingBean 045 public OkHttpClient okHttp3Client( 046 ObjectProvider<Cache> cache, 047 ObjectProvider<CookieJar> cookieJar, 048 ObjectProvider<Dns> dns, 049 ObjectProvider<HostnameVerifier> hostnameVerifier, 050 ObjectProvider<CertificatePinner> certificatePinner, 051 ConnectionPool connectionPool, 052 ObjectProvider<EventListener> eventListener 053 ) { 054 OkHttpClient.Builder builder = new OkHttpClient.Builder(); 055 056 cache.ifUnique(builder::cache); 057 058 eventListener.ifUnique(builder::eventListener); 059 060 builder.connectTimeout(okHttpProperties.getConnectTimeout().toMillis(), TimeUnit.MILLISECONDS); 061 builder.readTimeout(okHttpProperties.getReadTimeout().toMillis(), TimeUnit.MILLISECONDS); 062 builder.writeTimeout(okHttpProperties.getWriteTimeout().toMillis(), TimeUnit.MILLISECONDS); 063 builder.pingInterval(okHttpProperties.getPingInterval().toMillis(), TimeUnit.MILLISECONDS); 064 065 cookieJar.ifUnique(builder::cookieJar); 066 067 dns.ifUnique(builder::dns); 068 069 hostnameVerifier.ifUnique(builder::hostnameVerifier); 070 certificatePinner.ifUnique(builder::certificatePinner); 071 072 builder.connectionPool(connectionPool); 073 074 builder.followRedirects(okHttpProperties.isFollowRedirects()); 075 builder.followSslRedirects(okHttpProperties.isFollowSslRedirects()); 076 builder.retryOnConnectionFailure(okHttpProperties.isRetryOnConnectionFailure()); 077 078 applicationInterceptors.forEach(builder::addInterceptor); 079 080 networkInterceptors.forEach(builder::addNetworkInterceptor); 081 082 configurers.forEach(configurer -> configurer.configure(builder)); 083 084 return builder.build(); 085 } 086 087 @Bean 088 @ConditionalOnMissingBean 089 public ConnectionPool okHttp3ConnectionPool() { 090 int maxIdleConnections = okHttpProperties.getConnectionPool().getMaxIdleConnections(); 091 Duration keepAliveDuration = okHttpProperties.getConnectionPool().getKeepAliveDuration(); 092 return new ConnectionPool(maxIdleConnections, keepAliveDuration.toNanos(), TimeUnit.NANOSECONDS); 093 } 094 095 @Bean 096 @ConditionalOnMissingBean 097 @ConditionalOnProperty(value = "okhttp.cache.enabled", havingValue = "true", matchIfMissing = true) 098 public Cache okHttp3Cache() throws IOException { 099 File directory = okHttpProperties.getCache().getDirectory(); 100 if (directory == null) { 101 directory = Files.createTempDirectory("okhttp-cache").toFile(); 102 } 103 return new Cache(directory, okHttpProperties.getCache().getMaxSize().toBytes()); 104 } 105}