Package co.paralleluniverse.fibers.dropwizard

Source Code of co.paralleluniverse.fibers.dropwizard.FiberHttpClientBuilder

/*
* COMSAT
* Copyright (C) 2014, Parallel Universe Software Co. All rights reserved.
*
* This program and the accompanying materials are dual-licensed under
* either the terms of the Eclipse Public License v1.0 as published by
* the Eclipse Foundation
*
*   or (per the licensee's choosing)
*
* under the terms of the GNU Lesser General Public License version 3.0
* as published by the Free Software Foundation.
*/
package co.paralleluniverse.fibers.dropwizard;

import co.paralleluniverse.fibers.httpclient.FiberHttpClient;
import com.codahale.metrics.MetricRegistry;
import io.dropwizard.client.HttpClientConfiguration;
import io.dropwizard.setup.Environment;
import io.dropwizard.util.Duration;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.DnsResolver;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.conn.ssl.SSLInitializationException;
import org.apache.http.impl.DefaultConnectionReuseStrategy;
import org.apache.http.impl.NoConnectionReuseStrategy;
import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.conn.SchemeRegistryFactory;
import org.apache.http.impl.conn.SystemDefaultDnsResolver;
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.apache.http.impl.nio.conn.PoolingNHttpClientConnectionManager;
import org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor;
import org.apache.http.impl.nio.reactor.IOReactorConfig;
import org.apache.http.nio.conn.NHttpClientConnectionManager;
import org.apache.http.nio.conn.NoopIOSessionStrategy;
import org.apache.http.nio.conn.SchemeIOSessionStrategy;
import org.apache.http.nio.conn.ssl.SSLIOSessionStrategy;
import org.apache.http.nio.reactor.ConnectingIOReactor;
import org.apache.http.nio.reactor.IOReactorException;
import org.apache.http.protocol.HttpContext;

/**
* A convenience class for building {@link HttpClient} instances.
* <p>
* Among other things,
* <ul>
* <li>Disables stale connection checks</li>
* <li>Disables Nagle's algorithm</li>
* <li>Disables cookie management by default</li>
* </ul>
*/
public class FiberHttpClientBuilder {

    private final MetricRegistry metricRegistry;
    private HttpClientConfiguration configuration = new HttpClientConfiguration();
    private DnsResolver resolver = new SystemDefaultDnsResolver();
    private HttpRequestRetryHandler httpRequestRetryHandler;
    private SchemeRegistry registry = SchemeRegistryFactory.createSystemDefault();

    public FiberHttpClientBuilder(MetricRegistry metricRegistry) {
        this.metricRegistry = metricRegistry;
    }

    public FiberHttpClientBuilder(Environment environment) {
        this.metricRegistry = environment.metrics();
    }

    /**
     * Use the given {@link HttpClientConfiguration} instance.
     *
     * @param configuration a {@link HttpClientConfiguration} instance
     * @return {@code this}
     */
    public FiberHttpClientBuilder using(HttpClientConfiguration configuration) {
        this.configuration = configuration;
        return this;
    }

    /**
     * Use the given {@link DnsResolver} instance.
     *
     * @param resolver a {@link DnsResolver} instance
     * @return {@code this}
     */
    public FiberHttpClientBuilder using(DnsResolver resolver) {
        this.resolver = resolver;
        return this;
    }

    /**
     * Uses the {@link httpRequestRetryHandler} for handling request retries.
     *
     * @param httpRequestRetryHandler an httpRequestRetryHandler
     * @return {@code this}
     */
    public FiberHttpClientBuilder using(HttpRequestRetryHandler httpRequestRetryHandler) {
        this.httpRequestRetryHandler = httpRequestRetryHandler;
        return this;
    }

    /**
     * Use the given {@link SchemeRegistry} instance.
     *
     * @param registry a {@link SchemeRegistry} instance
     * @return {@code this}
     */
    public FiberHttpClientBuilder using(SchemeRegistry registry) {
        this.registry = registry;
        return this;
    }

    /**
     * Builds the {@link HttpClient}.
     *
     * @return an {@link HttpClient}
     */
    public HttpClient build(String name) {
        RequestConfig createHttpParams = createHttpParams();
        final NHttpClientConnectionManager manager = createConnectionManager(registry, name);
        HttpAsyncClientBuilder clientBuilder = new InstrumentedNHttpClientBuilder(metricRegistry, name);
        clientBuilder.setConnectionManager(manager);
        clientBuilder.setDefaultRequestConfig(createHttpParams);
        setStrategiesForClient(clientBuilder);
        CloseableHttpAsyncClient client = clientBuilder.build();
        client.start();
        return new FiberHttpClient(client, getRetryHandler());
    }

    /**
     * Add strategies to client such as ConnectionReuseStrategy and KeepAliveStrategy Note that this
     * method mutates the client object by setting the strategies
     *
     * @param client The InstrumentedHttpClient that should be configured with strategies
     */
    protected void setStrategiesForClient(HttpAsyncClientBuilder client) {
        final long keepAlive = configuration.getKeepAlive().toMilliseconds();

        // don't keep alive the HTTP connection and thus don't reuse the TCP socket
        if (keepAlive == 0) {
            client.setConnectionReuseStrategy(new NoConnectionReuseStrategy());
        } else {
            client.setConnectionReuseStrategy(new DefaultConnectionReuseStrategy());
            // either keep alive based on response header Keep-Alive,
            // or if the server can keep a persistent connection (-1), then override based on client's configuration
            client.setKeepAliveStrategy(new DefaultConnectionKeepAliveStrategy() {
                @Override
                public long getKeepAliveDuration(HttpResponse response, HttpContext context) {
                    final long duration = super.getKeepAliveDuration(response, context);
                    return (duration == -1) ? keepAlive : duration;
                }
            });
        }
    }

    private HttpRequestRetryHandler getRetryHandler() {
        return configuration.getRetries() == 0 ? null
                : httpRequestRetryHandler != null ? httpRequestRetryHandler
                : new DefaultHttpRequestRetryHandler(configuration.getRetries(), false);
    }

    /**
     * Map the parameters in HttpClientConfiguration to a BasicHttpParams object
     *
     * @return a BasicHttpParams object from the HttpClientConfiguration
     */
    protected RequestConfig createHttpParams() {
        RequestConfig.Builder rcb = RequestConfig.custom();
        rcb.setCookieSpec(CookieSpecs.BEST_MATCH);
        if (configuration.isCookiesEnabled())
            rcb.setCookieSpec(CookieSpecs.BEST_MATCH);
        else
            rcb.setCookieSpec(CookieSpecs.IGNORE_COOKIES);
        rcb.setStaleConnectionCheckEnabled(false);
        return rcb.build();
    }

    /**
     * Create a InstrumentedClientConnManager based on the HttpClientConfiguration. It sets the
     * maximum connections per route and the maximum total connections that the connection manager
     * can create
     *
     * @param registry the SchemeRegistry
     * @return a InstrumentedClientConnManger instance
     */
    protected NHttpClientConnectionManager createConnectionManager(SchemeRegistry registry, String name) {
        final Duration ttl = configuration.getTimeToLive();
        ConnectingIOReactor ioReactor = createDefaultIOReactor(IOReactorConfig.custom()
                .setSoTimeout((int) configuration.getTimeout().toMilliseconds())
                .setConnectTimeout((int) configuration.getConnectionTimeout().toMilliseconds())
                .setTcpNoDelay(true).build());

        PoolingNHttpClientConnectionManager manager
                = new InstrumentedNClientConnManager(
                        ioReactor, null, null, //TODO: add this parameters values
                        metricRegistry,
                        convertRegistry(this.registry),
                        ttl.getQuantity(),
                        ttl.getUnit(),
                        resolver,
                        name);
        manager.setDefaultMaxPerRoute(configuration.getMaxConnectionsPerRoute());
        manager.setMaxTotal(configuration.getMaxConnections());
        return manager;
    }

    private static ConnectingIOReactor createDefaultIOReactor(final IOReactorConfig spec) {
        try {
            return new DefaultConnectingIOReactor(spec);
        } catch (IOReactorException ex) {
            throw new RuntimeException(ex);
        }
    }

    private static Registry<SchemeIOSessionStrategy> convertRegistry(final SchemeRegistry oldRegistry) throws SSLInitializationException {
        SchemeRegistry baseRegistry = oldRegistry;
        //TODO: use values from old registry;
        Registry<SchemeIOSessionStrategy> defaultRegistry = RegistryBuilder.<SchemeIOSessionStrategy>create()
                .register("http", NoopIOSessionStrategy.INSTANCE)
                .register("https", new SSLIOSessionStrategy(
                                SSLContexts.createDefault(), null, null, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER))
                .build();
        return defaultRegistry;
    }

}
TOP

Related Classes of co.paralleluniverse.fibers.dropwizard.FiberHttpClientBuilder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.