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