org.zalando.stups.spring.http.client.ClientHttpRequestFactorySelector.java Source code

Java tutorial

Introduction

Here is the source code for org.zalando.stups.spring.http.client.ClientHttpRequestFactorySelector.java

Source

/**
 * Copyright (C) 2015 Zalando SE (http://tech.zalando.com)
 *
 * 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 org.zalando.stups.spring.http.client;

import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.URI;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Properties;

import javax.net.ssl.SSLContext;

import org.apache.http.HttpHost;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.protocol.HttpContext;
import org.springframework.http.HttpMethod;
import org.springframework.http.client.BufferingClientHttpRequestFactory;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.util.ClassUtils;

/**
 * Chooses a request factory. Picks a HttpComponentsClientRequestFactory factory if Apache HttpComponents HttpClient is in the classpath.
 * If not, falls back to SimpleClientHttpRequestFactory.
 * @author Craig Walls
 * @author Roy Clarkson
 */
public class ClientHttpRequestFactorySelector {

    public static ClientHttpRequestFactory foo() {
        return new HttpComponentsClientHttpRequestFactory();
    }

    /**
     * Builds a {@link ClientHttpRequestFactory} with timeout-defaults.
     * 
     * @return {@link ClientHttpRequestFactory}
     * @see TimeoutConfig.Builder for default-timeout values
     */
    public static ClientHttpRequestFactory getRequestFactory() {
        return getRequestFactory(TimeoutConfig.withDefaults());
    }

    public static ClientHttpRequestFactory getRequestFactory(TimeoutConfig timeoutConfig) {
        Properties properties = System.getProperties();
        String proxyHost = properties.getProperty("http.proxyHost");
        int proxyPort = properties.containsKey("http.proxyPort")
                ? Integer.valueOf(properties.getProperty("http.proxyPort"))
                : 80;
        if (HTTP_COMPONENTS_AVAILABLE) {
            HttpComponentsClientHttpRequestFactory factory = (HttpComponentsClientHttpRequestFactory) HttpComponentsClientRequestFactoryCreator
                    .createRequestFactory(proxyHost, proxyPort);
            factory.setReadTimeout(timeoutConfig.getReadTimeout());
            factory.setConnectTimeout(timeoutConfig.getConnectTimeout());
            factory.setConnectionRequestTimeout(timeoutConfig.getConnectionRequestTimeout());
            return factory;
        } else {
            SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
            requestFactory.setConnectTimeout(timeoutConfig.getConnectTimeout());
            requestFactory.setReadTimeout(timeoutConfig.getReadTimeout());
            if (proxyHost != null) {
                requestFactory.setProxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort)));
            }
            return requestFactory;
        }
    }

    /**
     * Decorates a request factory to buffer responses so that the responses may be repeatedly read.
     * @param requestFactory the request factory to be decorated for buffering
     * @return a buffering request factory
     */
    public static ClientHttpRequestFactory bufferRequests(ClientHttpRequestFactory requestFactory) {
        return new BufferingClientHttpRequestFactory(requestFactory);
    }

    private static final boolean HTTP_COMPONENTS_AVAILABLE = ClassUtils
            .isPresent("org.apache.http.client.HttpClient", ClientHttpRequestFactory.class.getClassLoader());

    public static class HttpComponentsClientRequestFactoryCreator {

        private static boolean isAllTrust = false;

        public static ClientHttpRequestFactory createRequestFactory(String proxyHost, int proxyPort) {

            HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory() {
                @Override
                protected HttpContext createHttpContext(HttpMethod httpMethod, URI uri) {
                    HttpClientContext context = new HttpClientContext();
                    context.setAttribute("http.protocol.expect-continue", false);
                    return context;
                }
            };

            if (proxyHost != null) {
                HttpHost proxy = new HttpHost(proxyHost, proxyPort);
                CloseableHttpClient httpClient = isAllTrust ? getAllTrustClient(proxy) : getClient(proxy);
                requestFactory.setHttpClient(httpClient);
            }

            return requestFactory;

        }

        private static CloseableHttpClient getClient(HttpHost proxy) {
            return HttpClients.custom().setProxy(proxy).build();
        }

        private static CloseableHttpClient getAllTrustClient(HttpHost proxy) {
            return HttpClients.custom().setProxy(proxy).setSSLContext(getSSLContext())
                    .setSSLHostnameVerifier(new NoopHostnameVerifier()).build();
        }

        private static SSLContext getSSLContext() {
            try {
                KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
                TrustStrategy allTrust = new TrustStrategy() {
                    @Override
                    public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                        return true;
                    }
                };
                return org.apache.http.ssl.SSLContexts.custom().loadTrustMaterial(trustStore, allTrust).build();
            } catch (KeyStoreException e) {
                e.printStackTrace();
            } catch (KeyManagementException e) {
                e.printStackTrace();
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
            return null;
        }

    }

    /**
     * Trust all SSL certificates.
     * For use when using {@link HttpComponentsClientHttpRequestFactory} in a test environment. Not recommended for general use.
     * @param isAllTrust if true, all certificates will be trusted.
     */
    public static void setAllTrust(boolean isAllTrust) {
        HttpComponentsClientRequestFactoryCreator.isAllTrust = isAllTrust;
    }

}