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