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.condition.ConditionalOnClass;
007import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
008import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
009import org.springframework.boot.context.properties.EnableConfigurationProperties;
010import org.springframework.context.annotation.Bean;
011import org.springframework.context.annotation.Configuration;
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@Configuration(proxyBeanMethods = false)
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    ) {
050        OkHttpClient.Builder builder = new OkHttpClient.Builder();
051
052        cache.ifUnique(builder::cache);
053
054        builder.connectTimeout(okHttpProperties.getConnectTimeout().toMillis(), TimeUnit.MILLISECONDS);
055        builder.readTimeout(okHttpProperties.getReadTimeout().toMillis(), TimeUnit.MILLISECONDS);
056        builder.writeTimeout(okHttpProperties.getWriteTimeout().toMillis(), TimeUnit.MILLISECONDS);
057        builder.pingInterval(okHttpProperties.getPingInterval().toMillis(), TimeUnit.MILLISECONDS);
058
059        cookieJar.ifUnique(builder::cookieJar);
060
061        dns.ifUnique(builder::dns);
062
063        builder.connectionPool(connectionPool);
064
065        builder.followRedirects(okHttpProperties.isFollowRedirects());
066        builder.followSslRedirects(okHttpProperties.isFollowSslRedirects());
067        builder.retryOnConnectionFailure(okHttpProperties.isRetryOnConnectionFailure());
068
069        applicationInterceptors.forEach(builder::addInterceptor);
070
071        networkInterceptors.forEach(builder::addNetworkInterceptor);
072
073        configurers.forEach(configurer -> configurer.configure(builder));
074
075        return builder.build();
076    }
077
078    @Bean
079    @ConditionalOnMissingBean
080    public ConnectionPool okHttp3ConnectionPool() {
081        int maxIdleConnections = okHttpProperties.getConnectionPool().getMaxIdleConnections();
082        Duration keepAliveDuration = okHttpProperties.getConnectionPool().getKeepAliveDuration();
083        return new ConnectionPool(maxIdleConnections, keepAliveDuration.toNanos(), TimeUnit.NANOSECONDS);
084    }
085
086    @Bean
087    @ConditionalOnMissingBean
088    @ConditionalOnProperty(value = "okhttp.cache.enabled", havingValue = "true", matchIfMissing = true)
089    public Cache okHttp3Cache() throws IOException {
090        File directory = okHttpProperties.getCache().getDirectory();
091        if (directory == null) {
092            directory = Files.createTempDirectory("okhttp-cache").toFile();
093        }
094        return new Cache(directory, okHttpProperties.getCache().getMaxSize().toBytes());
095    }
096}