001package io.freefair.spring.okhttp.autoconfigure;
002
003import io.freefair.spring.okhttp.client.OkHttpClientRequestFactory;
004import okhttp3.OkHttpClient;
005import org.springframework.boot.http.client.ClientHttpRequestFactoryBuilder;
006import org.springframework.boot.http.client.ClientHttpRequestFactorySettings;
007import org.springframework.boot.ssl.SslBundle;
008import org.springframework.lang.Nullable;
009import org.springframework.util.Assert;
010import javax.net.ssl.SSLContext;
011import javax.net.ssl.SSLSocketFactory;
012import javax.net.ssl.TrustManager;
013import javax.net.ssl.X509TrustManager;
014import java.time.Duration;
015
016/**
017 * @author Lars Grefer
018 */
019public class OkHttpClientRequestFactoryBuilder implements ClientHttpRequestFactoryBuilder<OkHttpClientRequestFactory> {
020    private final OkHttpClient okHttpClient;
021
022    @Override
023    public OkHttpClientRequestFactory build() {
024        return this.build(null);
025    }
026
027    @Override
028    public OkHttpClientRequestFactory build(@Nullable ClientHttpRequestFactorySettings settings) {
029        OkHttpClient.Builder builder = okHttpClient.newBuilder();
030        if (settings == null) {
031            return new OkHttpClientRequestFactory(builder.build());
032        }
033        Duration connectTimeout = settings.connectTimeout();
034        if (connectTimeout != null) {
035            builder.connectTimeout(connectTimeout);
036        }
037        Duration readTimeout = settings.readTimeout();
038        if (readTimeout != null) {
039            builder.readTimeout(readTimeout);
040        }
041        SslBundle sslBundle = settings.sslBundle();
042        if (sslBundle != null) {
043            Assert.state(!sslBundle.getOptions().isSpecified(), "SSL Options cannot be specified with OkHttp");
044            SSLContext sslContext = sslBundle.createSslContext();
045            SSLSocketFactory socketFactory = sslContext.getSocketFactory();
046            TrustManager[] trustManagers = sslBundle.getManagers().getTrustManagers();
047            Assert.state(trustManagers.length == 1, "Trust material must be provided in the SSL bundle for OkHttp3ClientHttpRequestFactory");
048            builder.sslSocketFactory(socketFactory, (X509TrustManager) trustManagers[0]);
049        }
050        ClientHttpRequestFactorySettings.Redirects redirects = settings.redirects();
051        if (redirects != null) {
052            switch (redirects) {
053                case FOLLOW_WHEN_POSSIBLE, FOLLOW -> {
054                    builder.followRedirects(true);
055                    builder.followSslRedirects(true);
056                }
057                case DONT_FOLLOW -> {
058                    builder.followRedirects(false);
059                    builder.followSslRedirects(true);
060                }
061                default -> {
062                }
063            }
064        }
065        return new OkHttpClientRequestFactory(builder.build());
066    }
067
068    public OkHttpClientRequestFactoryBuilder(final OkHttpClient okHttpClient) {
069        this.okHttpClient = okHttpClient;
070    }
071}