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