package top.quantic.sentry.config;

import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.cache.CacheConfig;
import org.apache.http.impl.client.cache.CachingHttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;

@Configuration
public class HttpClientConfiguration {

    private static final Logger log = LoggerFactory.getLogger(HttpClientConfiguration.class);

    @Autowired
    private SentryProperties sentryProperties;

    @Bean
    public ClientHttpRequestFactory httpRequestFactory() {
        return new HttpComponentsClientHttpRequestFactory(httpClient());
    }

    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate(httpRequestFactory());
    }

    @Bean
    public CloseableHttpClient httpClient() {
        RequestConfig requestConfig = RequestConfig.custom()
            .setConnectTimeout(properties().getReadTimeout())
            .setSocketTimeout(properties().getSocketTimeout())
            .build();

        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
        connectionManager.setMaxTotal(properties().getMaxTotalConnections());
        connectionManager.setDefaultMaxPerRoute(properties().getMaxConnectionsPerRoute());

        CacheConfig cacheConfig = CacheConfig.custom()
            .setMaxCacheEntries(properties().getMaxCacheEntries())
            .setMaxObjectSize(properties().getMaxObjectSize())
            .setHeuristicCachingEnabled(true) // important!
            .build();

        File cacheDir = new File(properties().getCacheDir());
        try {
            Files.createDirectories(cacheDir.toPath());
        } catch (IOException e) {
            log.warn("Could not create cache directory - using temp folder", e);
            try {
                cacheDir = Files.createTempDirectory("cache").toFile();
            } catch (IOException ee) {
                log.warn("Could not create temp cache directory", ee);
            }
        }

        return CachingHttpClients.custom()
            .setCacheConfig(cacheConfig)
            .setCacheDir(cacheDir)
            .setDefaultRequestConfig(requestConfig)
            .setConnectionManager(connectionManager)
            .build();
    }

    private SentryProperties.Http properties() {
        return sentryProperties.getHttp();
    }
}

@@ -252,16 +252,144 @@
 lients;%0A
+import org.apache.http.impl.client.cache.FileResourceFactory;%0Aimport org.apache.http.impl.client.cache.ManagedHttpCacheStorage;%0A
 import o
@@ -498,32 +498,89 @@
 .LoggerFactory;%0A
+import org.springframework.beans.factory.DisposableBean;%0A
 import org.sprin
@@ -1066,16 +1066,42 @@
 uration 
+implements DisposableBean 
 %7B%0A%0A    p
@@ -1253,16 +1253,107 @@
 rties;%0A%0A
+    private CloseableHttpClient client;%0A    private ManagedHttpCacheStorage cacheStorage;%0A%0A
     @Bea
@@ -2894,22 +2894,171 @@
         
-return
+FileResourceFactory resourceFactory = new FileResourceFactory(cacheDir);%0A        cacheStorage = new ManagedHttpCacheStorage(cacheConfig);%0A%0A        client =
  Caching
@@ -3139,25 +3139,86 @@
 .set
-CacheDir(cacheDir
+ResourceFactory(resourceFactory)%0A            .setHttpCacheStorage(cacheStorage
 )%0A  
@@ -3341,16 +3341,40 @@
 build();
+%0A%0A        return client;
 %0A    %7D%0A%0A
@@ -3470,11 +3470,198 @@
 );%0A    %7D
+%0A%0A    @Override%0A    public void destroy() throws Exception %7B%0A        log.debug(%22Closing HttpClient and CacheStorage%22);%0A        client.close();%0A        cacheStorage.cleanResources();%0A    %7D
 %0A%7D%0A

Update HttpClientConfiguration