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}