Package io.dropwizard.jetty

Source Code of io.dropwizard.jetty.HttpConnectorFactory

package io.dropwizard.jetty;

import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.jetty9.InstrumentedConnectionFactory;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonTypeName;
import io.dropwizard.util.Duration;
import io.dropwizard.util.Size;
import io.dropwizard.util.SizeUnit;
import io.dropwizard.validation.MinDuration;
import io.dropwizard.validation.MinSize;
import io.dropwizard.validation.PortRange;
import org.eclipse.jetty.io.ArrayByteBufferPool;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.server.*;
import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler;
import org.eclipse.jetty.util.thread.Scheduler;
import org.eclipse.jetty.util.thread.ThreadPool;

import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import java.util.concurrent.TimeUnit;

import static com.codahale.metrics.MetricRegistry.name;

/**
* Builds HTTP connectors.
*
* <p/>
* <b>Configuration Parameters:</b>
* <table>
*     <tr>
*         <td>Name</td>
*         <td>Default</td>
*         <td>Description</td>
*     </tr>
*     <tr>
*         <td>{@code port}</td>
*         <td>8080</td>
*         <td>The TCP/IP port on which to listen for incoming connections.</td>
*     </tr>
*     <tr>
*         <td>{@code bindHost}</td>
*         <td>(none)</td>
*         <td>The hostname to bind to.</td>
*     </tr>
*     <tr>
*         <td>{@code headerCacheSize}</td>
*         <td>512 bytes</td>
*         <td>The size of the header field cache.</td>
*     </tr>
*     <tr>
*         <td>{@code outputBufferSize}</td>
*         <td>32KiB</td>
*         <td>
*             The size of the buffer into which response content is aggregated before being sent to
*             the client.  A larger buffer can improve performance by allowing a content producer
*             to run without blocking, however larger buffers consume more memory and may induce
*             some latency before a client starts processing the content.
*         </td>
*     </tr>
*     <tr>
*         <td>{@code maxRequestHeaderSize}</td>
*         <td>8KiB</td>
*         <td>
*             The maximum size of a request header. Larger headers will allow for more and/or
*             larger cookies plus larger form content encoded  in a URL. However, larger headers
*             consume more memory and can make a server more vulnerable to denial of service
*             attacks.
*         </td>
*     </tr>
*     <tr>
*         <td>{@code maxResponseHeaderSize}</td>
*         <td>8KiB</td>
*         <td>
*             The maximum size of a response header. Larger headers will allow for more and/or
*             larger cookies and longer HTTP headers (eg for redirection).  However, larger headers
*             will also consume more memory.
*         </td>
*     </tr>
*     <tr>
*         <td>{@code inputBufferSize}</td>
*         <td>8KiB</td>
*         <td>The size of the per-connection input buffer.</td>
*     </tr>
*     <tr>
*         <td>{@code idleTimeout}</td>
*         <td>30 seconds</td>
*         <td>
*             The maximum idle time for a connection, which roughly translates to the
*             {@link java.net.Socket#setSoTimeout(int)} call, although with NIO implementations
*             other mechanisms may be used to implement the timeout.
*             <p/>
*             The max idle time is applied:
*             <ul>
*                 <li>When waiting for a new message to be received on a connection</li>
*                 <li>When waiting for a new message to be sent on a connection</li>
*             </ul>
*             <p/>
*             This value is interpreted as the maximum time between some progress being made on the
*             connection. So if a single byte is read or written, then the timeout is reset.
*         </td>
*     </tr>
*     <tr>
*         <td>{@code minBufferPoolSize}</td>
*         <td>64 bytes</td>
*         <td>The minimum size of the buffer pool.</td>
*     </tr>
*     <tr>
*         <td>{@code bufferPoolIncrement}</td>
*         <td>1KiB</td>
*         <td>The increment by which the buffer pool should be increased.</td>
*     </tr>
*     <tr>
*         <td>{@code maxBufferPoolSize}</td>
*         <td>64KiB</td>
*         <td>The maximum size of the buffer pool.</td>
*     </tr>
*     <tr>
*         <td>{@code acceptorThreads}</td>
*         <td>half the # of CPUs</td>
*         <td>The number of worker threads dedicated to accepting connections.</td>
*     </tr>
*     <tr>
*         <td>{@code selectorThreads}</td>
*         <td>the # of CPUs</td>
*         <td>The number of worker threads dedicated to sending and receiving data.</td>
*     </tr>
*     <tr>
*         <td>{@code acceptQueueSize}</td>
*         <td>(OS default)</td>
*         <td>The size of the TCP/IP accept queue for the listening socket.</td>
*     </tr>
*     <tr>
*         <td>{@code reuseAddress}</td>
*         <td>true</td>
*         <td>Whether or not {@code SO_REUSEADDR} is enabled on the listening socket.</td>
*     </tr>
*     <tr>
*         <td>{@code soLingerTime}</td>
*         <td>(disabled)</td>
*         <td>Enable/disable {@code SO_LINGER} with the specified linger time.</td>
*     </tr>
*     <tr>
*         <td>{@code useServerHeader}</td>
*         <td>false</td>
*         <td>Whether or not to add the {@code Server} header to each response.</td>
*     </tr>
*     <tr>
*         <td>{@code useDateHeader}</td>
*         <td>true</td>
*         <td>Whether or not to add the {@code Date} header to each response.</td>
*     </tr>
*     <tr>
*         <td>{@code useForwardedHeaders}</td>
*         <td>true</td>
*         <td>
*             Whether or not to look at {@code X-Forwarded-*} headers added by proxies. See
*             {@link ForwardedRequestCustomizer} for details.
*         </td>
*     </tr>
* </table>
*/
@JsonTypeName("http")
public class HttpConnectorFactory implements ConnectorFactory {
    public static ConnectorFactory application() {
        final HttpConnectorFactory factory = new HttpConnectorFactory();
        factory.port = 8080;
        return factory;
    }

    public static ConnectorFactory admin() {
        final HttpConnectorFactory factory = new HttpConnectorFactory();
        factory.port = 8081;
        return factory;
    }

    @PortRange
    private int port = 8080;

    private String bindHost = null;

    @NotNull
    @MinSize(128)
    private Size headerCacheSize = Size.bytes(512);

    @NotNull
    @MinSize(value = 8, unit = SizeUnit.KILOBYTES)
    private Size outputBufferSize = Size.kilobytes(32);

    @NotNull
    @MinSize(value = 1, unit = SizeUnit.KILOBYTES)
    private Size maxRequestHeaderSize = Size.kilobytes(8);

    @NotNull
    @MinSize(value = 1, unit = SizeUnit.KILOBYTES)
    private Size maxResponseHeaderSize = Size.kilobytes(8);

    @NotNull
    @MinSize(value = 1, unit = SizeUnit.KILOBYTES)
    private Size inputBufferSize = Size.kilobytes(8);

    @NotNull
    @MinDuration(value = 1, unit = TimeUnit.MILLISECONDS)
    private Duration idleTimeout = Duration.seconds(30);

    @NotNull
    @MinSize(value = 1, unit = SizeUnit.BYTES)
    private Size minBufferPoolSize = Size.bytes(64);

    @NotNull
    @MinSize(value = 1, unit = SizeUnit.BYTES)
    private Size bufferPoolIncrement = Size.bytes(1024);

    @NotNull
    @MinSize(value = 1, unit = SizeUnit.BYTES)
    private Size maxBufferPoolSize = Size.kilobytes(64);

    @Min(1)
    private int acceptorThreads = Math.max(1, Runtime.getRuntime().availableProcessors() / 2);

    @Min(1)
    private int selectorThreads = Runtime.getRuntime().availableProcessors();

    @Min(0)
    private Integer acceptQueueSize;

    private boolean reuseAddress = true;
    private Duration soLingerTime = null;
    private boolean useServerHeader = false;
    private boolean useDateHeader = true;
    private boolean useForwardedHeaders = true;

    @JsonProperty
    public int getPort() {
        return port;
    }

    @JsonProperty
    public void setPort(int port) {
        this.port = port;
    }

    @JsonProperty
    public String getBindHost() {
        return bindHost;
    }

    @JsonProperty
    public void setBindHost(String bindHost) {
        this.bindHost = bindHost;
    }

    @JsonProperty
    public Size getHeaderCacheSize() {
        return headerCacheSize;
    }

    @JsonProperty
    public void setHeaderCacheSize(Size headerCacheSize) {
        this.headerCacheSize = headerCacheSize;
    }

    @JsonProperty
    public Size getOutputBufferSize() {
        return outputBufferSize;
    }

    @JsonProperty
    public void setOutputBufferSize(Size outputBufferSize) {
        this.outputBufferSize = outputBufferSize;
    }

    @JsonProperty
    public Size getMaxRequestHeaderSize() {
        return maxRequestHeaderSize;
    }

    @JsonProperty
    public void setMaxRequestHeaderSize(Size maxRequestHeaderSize) {
        this.maxRequestHeaderSize = maxRequestHeaderSize;
    }

    @JsonProperty
    public Size getMaxResponseHeaderSize() {
        return maxResponseHeaderSize;
    }

    @JsonProperty
    public void setMaxResponseHeaderSize(Size maxResponseHeaderSize) {
        this.maxResponseHeaderSize = maxResponseHeaderSize;
    }

    @JsonProperty
    public Size getInputBufferSize() {
        return inputBufferSize;
    }

    @JsonProperty
    public void setInputBufferSize(Size inputBufferSize) {
        this.inputBufferSize = inputBufferSize;
    }

    @JsonProperty
    public Duration getIdleTimeout() {
        return idleTimeout;
    }

    @JsonProperty
    public void setIdleTimeout(Duration idleTimeout) {
        this.idleTimeout = idleTimeout;
    }

    @JsonProperty
    public Size getMinBufferPoolSize() {
        return minBufferPoolSize;
    }

    @JsonProperty
    public void setMinBufferPoolSize(Size minBufferPoolSize) {
        this.minBufferPoolSize = minBufferPoolSize;
    }

    @JsonProperty
    public Size getBufferPoolIncrement() {
        return bufferPoolIncrement;
    }

    @JsonProperty
    public void setBufferPoolIncrement(Size bufferPoolIncrement) {
        this.bufferPoolIncrement = bufferPoolIncrement;
    }

    @JsonProperty
    public Size getMaxBufferPoolSize() {
        return maxBufferPoolSize;
    }

    @JsonProperty
    public void setMaxBufferPoolSize(Size maxBufferPoolSize) {
        this.maxBufferPoolSize = maxBufferPoolSize;
    }

    @JsonProperty
    public int getAcceptorThreads() {
        return acceptorThreads;
    }

    @JsonProperty
    public void setAcceptorThreads(int acceptorThreads) {
        this.acceptorThreads = acceptorThreads;
    }

    @JsonProperty
    public int getSelectorThreads() {
        return selectorThreads;
    }

    @JsonProperty
    public void setSelectorThreads(int selectorThreads) {
        this.selectorThreads = selectorThreads;
    }

    @JsonProperty
    public Integer getAcceptQueueSize() {
        return acceptQueueSize;
    }

    @JsonProperty
    public void setAcceptQueueSize(Integer acceptQueueSize) {
        this.acceptQueueSize = acceptQueueSize;
    }

    @JsonProperty
    public boolean isReuseAddress() {
        return reuseAddress;
    }

    @JsonProperty
    public void setReuseAddress(boolean reuseAddress) {
        this.reuseAddress = reuseAddress;
    }

    @JsonProperty
    public Duration getSoLingerTime() {
        return soLingerTime;
    }

    @JsonProperty
    public void setSoLingerTime(Duration soLingerTime) {
        this.soLingerTime = soLingerTime;
    }

    @JsonProperty
    public boolean isUseServerHeader() {
        return useServerHeader;
    }

    @JsonProperty
    public void setUseServerHeader(boolean useServerHeader) {
        this.useServerHeader = useServerHeader;
    }

    @JsonProperty
    public boolean isUseDateHeader() {
        return useDateHeader;
    }

    @JsonProperty
    public void setUseDateHeader(boolean useDateHeader) {
        this.useDateHeader = useDateHeader;
    }

    @JsonProperty
    public boolean isUseForwardedHeaders() {
        return useForwardedHeaders;
    }

    @JsonProperty
    public void setUseForwardedHeaders(boolean useForwardedHeaders) {
        this.useForwardedHeaders = useForwardedHeaders;
    }

    @Override
    public Connector build(Server server,
                           MetricRegistry metrics,
                           String name,
                           ThreadPool threadPool) {
        final HttpConfiguration httpConfig = buildHttpConfiguration();

        final HttpConnectionFactory httpConnectionFactory = buildHttpConnectionFactory(httpConfig);

        final Scheduler scheduler = new ScheduledExecutorScheduler();

        final ByteBufferPool bufferPool = buildBufferPool();

        final String timerName = name(HttpConnectionFactory.class,
                                      bindHost,
                                      Integer.toString(port),
                                      "connections");
        return buildConnector(server, scheduler, bufferPool, name, threadPool,
                              new InstrumentedConnectionFactory(httpConnectionFactory,
                                                                metrics.timer(timerName)));
    }

    protected ServerConnector buildConnector(Server server,
                                             Scheduler scheduler,
                                             ByteBufferPool bufferPool,
                                             String name,
                                             ThreadPool threadPool,
                                             ConnectionFactory... factories) {
        final ServerConnector connector = new ServerConnector(server,
                                                              threadPool,
                                                              scheduler,
                                                              bufferPool,
                                                              acceptorThreads,
                                                              selectorThreads,
                                                              factories);
        connector.setPort(port);
        connector.setHost(bindHost);
        if (acceptQueueSize != null) {
            connector.setAcceptQueueSize(acceptQueueSize);
        }
        connector.setReuseAddress(reuseAddress);
        if (soLingerTime != null) {
            connector.setSoLingerTime((int) soLingerTime.toSeconds());
        }
        connector.setIdleTimeout(idleTimeout.toMilliseconds());
        connector.setName(name);

        return connector;
    }

    protected HttpConnectionFactory buildHttpConnectionFactory(HttpConfiguration httpConfig) {
        final HttpConnectionFactory httpConnectionFactory = new HttpConnectionFactory(httpConfig);
        httpConnectionFactory.setInputBufferSize((int) inputBufferSize.toBytes());
        return httpConnectionFactory;
    }

    protected HttpConfiguration buildHttpConfiguration() {
        final HttpConfiguration httpConfig = new HttpConfiguration();
        httpConfig.setHeaderCacheSize((int) headerCacheSize.toBytes());
        httpConfig.setOutputBufferSize((int) outputBufferSize.toBytes());
        httpConfig.setRequestHeaderSize((int) maxRequestHeaderSize.toBytes());
        httpConfig.setResponseHeaderSize((int) maxResponseHeaderSize.toBytes());
        httpConfig.setSendDateHeader(useDateHeader);
        httpConfig.setSendServerVersion(useServerHeader);

        if (useForwardedHeaders) {
            httpConfig.addCustomizer(new ForwardedRequestCustomizer());
        }
        return httpConfig;
    }

    protected ByteBufferPool buildBufferPool() {
        return new ArrayByteBufferPool((int) minBufferPoolSize.toBytes(),
                                       (int) bufferPoolIncrement.toBytes(),
                                       (int) maxBufferPoolSize.toBytes());
    }
}
TOP

Related Classes of io.dropwizard.jetty.HttpConnectorFactory

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.