io.fabric8.docker.client.utils.HttpClientUtils.java Source code

Java tutorial

Introduction

Here is the source code for io.fabric8.docker.client.utils.HttpClientUtils.java

Source

/*
 * Copyright (C) 2016 Original Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
package io.fabric8.docker.client.utils;

import com.squareup.okhttp.Authenticator;
import com.squareup.okhttp.Challenge;
import com.squareup.okhttp.ConnectionPool;
import com.squareup.okhttp.Credentials;
import com.squareup.okhttp.HttpUrl;
import com.squareup.okhttp.Interceptor;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;
import com.squareup.okhttp.logging.HttpLoggingInterceptor;
import io.fabric8.docker.client.Config;
import io.fabric8.docker.client.DockerClientException;
import io.fabric8.docker.client.unix.UnixSocketFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.Proxy;
import java.net.URL;
import java.security.GeneralSecurityException;
import java.util.List;
import java.util.concurrent.TimeUnit;

import static io.fabric8.docker.client.utils.Utils.isNotNullOrEmpty;

public class HttpClientUtils {

    //Let's fool okhttp to work with non http schemes!
    //How?
    //We pass a fake url and a custom socket factory.
    private static final String UNIX_FAKE_URL = "http://localhost:80";

    private static final String UNIX_SCHEME = "unix";
    private static final String FILE_SCHEME = "file";

    public static OkHttpClient createHttpClient(final Config config) {
        try {
            OkHttpClient httpClient = new OkHttpClient();

            httpClient.setConnectionPool(ConnectionPool.getDefault());
            // Follow any redirects
            httpClient.setFollowRedirects(true);
            httpClient.setFollowSslRedirects(true);

            if (config.isTrustCerts()) {
                httpClient.setHostnameVerifier(new HostnameVerifier() {
                    @Override
                    public boolean verify(String s, SSLSession sslSession) {
                        return true;
                    }
                });
            }

            if (usesUnixSocket(config)) {
                URL masterURL = new URL(config.getDockerUrl().replaceFirst(UNIX_SCHEME, FILE_SCHEME));
                httpClient.setSocketFactory(new UnixSocketFactory(masterURL.getFile()));
                config.setDockerUrl(UNIX_FAKE_URL);
            }

            TrustManager[] trustManagers = SSLUtils.trustManagers(config);
            KeyManager[] keyManagers = SSLUtils.keyManagers(config);

            if (keyManagers != null || trustManagers != null || config.isTrustCerts()) {
                try {
                    SSLContext sslContext = SSLUtils.sslContext(keyManagers, trustManagers, config.isTrustCerts());
                    httpClient.setSslSocketFactory(sslContext.getSocketFactory());
                } catch (GeneralSecurityException e) {
                    throw new AssertionError(); // The system has no TLS. Just give up.
                }
            }

            if (isNotNullOrEmpty(config.getUsername()) && isNotNullOrEmpty(config.getPassword())) {
                httpClient.setAuthenticator(new Authenticator() {

                    @Override
                    public Request authenticate(Proxy proxy, Response response) throws IOException {
                        List<Challenge> challenges = response.challenges();
                        Request request = response.request();
                        HttpUrl url = request.httpUrl();
                        for (int i = 0, size = challenges.size(); i < size; i++) {
                            Challenge challenge = challenges.get(i);
                            if (!"Basic".equalsIgnoreCase(challenge.getScheme()))
                                continue;

                            String credential = Credentials.basic(config.getUsername(), config.getPassword());
                            return request.newBuilder().header("Authorization", credential).build();
                        }
                        return null;
                    }

                    @Override
                    public Request authenticateProxy(Proxy proxy, Response response) throws IOException {
                        return null;
                    }
                });
            } else if (config.getOauthToken() != null) {
                httpClient.interceptors().add(new Interceptor() {
                    @Override
                    public Response intercept(Chain chain) throws IOException {
                        Request authReq = chain.request().newBuilder()
                                .addHeader("Authorization", "Bearer " + config.getOauthToken()).build();
                        return chain.proceed(authReq);
                    }
                });
            }

            Logger reqLogger = LoggerFactory.getLogger(HttpLoggingInterceptor.class);
            if (reqLogger.isTraceEnabled()) {
                HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
                loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
                httpClient.networkInterceptors().add(loggingInterceptor);
            }

            if (config.getConnectionTimeout() > 0) {
                httpClient.setConnectTimeout(config.getConnectionTimeout(), TimeUnit.MILLISECONDS);
            }

            if (config.getRequestTimeout() > 0) {
                httpClient.setReadTimeout(config.getRequestTimeout(), TimeUnit.MILLISECONDS);
            }

            // Only check proxy if it's a full URL with protocol
            if (config.getDockerUrl().toLowerCase().startsWith(Config.HTTP_PROTOCOL_PREFIX)
                    || config.getDockerUrl().startsWith(Config.HTTPS_PROTOCOL_PREFIX)) {
                try {
                    URL proxyUrl = getProxyUrl(config);
                    if (proxyUrl != null) {
                        httpClient.setProxy(new Proxy(Proxy.Type.HTTP,
                                new InetSocketAddress(proxyUrl.getHost(), proxyUrl.getPort())));
                    }
                } catch (MalformedURLException e) {
                    throw new DockerClientException("Invalid proxy server configuration", e);
                }
            }

            return httpClient;
        } catch (Exception e) {
            throw DockerClientException.launderThrowable(e);
        }
    }

    private static URL getProxyUrl(Config config) throws MalformedURLException {
        URL master = new URL(config.getDockerUrl());
        String host = master.getHost();
        for (String noProxy : config.getNoProxy()) {
            if (host.endsWith(noProxy)) {
                return null;
            }
        }
        String proxy = config.getHttpsProxy();
        if (master.getProtocol().equals("http")) {
            proxy = config.getHttpProxy();
        }
        if (proxy != null) {
            return new URL(proxy);
        }
        return null;
    }

    private static boolean usesUnixSocket(Config config) {
        return config.getDockerUrl().startsWith(UNIX_SCHEME);
    }
}