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