<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE preface PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
                 "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
<!--
   ====================================================================
   Licensed to the Apache Software Foundation (ASF) under one
   or more contributor license agreements.  See the NOTICE file
   distributed with this work for additional information
   regarding copyright ownership.  The ASF licenses this file
   to you 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.
   ====================================================================

-->
<chapter id="blocking-io">
    <title>Blocking I/O model</title>
    <para>Blocking (or classic) I/O in Java represents a highly efficient and convenient I/O model
    well suited for high performance applications where the number of concurrent connections is
    relatively moderate. Modern JVMs are capable of efficient context switching and the blocking
    I/O model should offer the best performance in terms of raw data throughput as long as
    the number of concurrent connections is below one thousand and connections are mostly busy
    transmitting data. However for applications where connections stay idle most of the time
    the overhead of context switching may become substantial and a non-blocking I/O model may
    present a better alternative.</para>
    <section>
        <title>Blocking HTTP connections</title>
        <para>
        HTTP connections are responsible for HTTP message serialization and deserialization. One
        should rarely need to use HTTP connection objects directly. There are higher level protocol
        components intended for execution and processing of HTTP requests. However, in some cases
        direct interaction with HTTP connections may be necessary, for instance, to access
        properties such as the connection status, the socket timeout or the local and remote
        addresses.
        </para>
        <para>
        It is important to bear in mind that HTTP connections are not thread-safe. We strongly
        recommend limiting all interactions with HTTP connection objects to one thread. The only
        method of <interfacename>HttpConnection</interfacename> interface and its sub-interfaces
        which is safe to invoke from another thread is <methodname> HttpConnection#shutdown()
        </methodname>.
        </para>
        <section>
            <title>Working with blocking HTTP connections</title>
            <para>
            HttpCore does not provide full support for opening connections because the process of
            establishing a new connection - especially on the client side - can be very complex
            when it involves one or more authenticating or/and tunneling proxies. Instead, blocking
            HTTP connections can be bound to any arbitrary network socket.
            </para>
            <programlisting><![CDATA[
Socket socket = <...>

DefaultBHttpClientConnection conn = new DefaultBHttpClientConnection(8 * 1024);
conn.bind(socket);
System.out.println(conn.isOpen());
HttpConnectionMetrics metrics = conn.getMetrics();
System.out.println(metrics.getRequestCount());
System.out.println(metrics.getResponseCount());
System.out.println(metrics.getReceivedBytesCount());
System.out.println(metrics.getSentBytesCount());
]]></programlisting>
            <para>
            HTTP connection interfaces, both client and server, send and receive messages in two
            stages. The message head is transmitted first. Depending on properties of the message
            head, a message body may follow it. Please note it is very important to always
            close the underlying content stream in order to signal that the processing of
            the message is complete. HTTP entities that stream out their content directly from the
            input stream of the underlying connection must ensure they fully consume the content
            of the message body for that connection to be potentially re-usable.
            </para>
            <para>
            Over-simplified process of request execution on the client side may look like this:
            </para>
            <programlisting><![CDATA[
Socket socket = <...>

DefaultBHttpClientConnection conn = new DefaultBHttpClientConnection(8 * 1024);
conn.bind(socket);
HttpRequest request = new BasicHttpRequest("GET", "/");
conn.sendRequestHeader(request);
HttpResponse response = conn.receiveResponseHeader();
conn.receiveResponseEntity(response);
HttpEntity entity = response.getEntity();
if (entity != null) {
    // Do something useful with the entity and, when done, ensure all
    // content has been consumed, so that the underlying connection
    // can be re-used
    EntityUtils.consume(entity);
}
]]></programlisting>
            <para>
            Over-simplified process of request handling on the server side may look like this:
            </para>
            <programlisting><![CDATA[
Socket socket = <...>

DefaultBHttpServerConnection conn = new DefaultBHttpServerConnection(8 * 1024);
conn.bind(socket);
HttpRequest request = conn.receiveRequestHeader();
if (request instanceof HttpEntityEnclosingRequest) {
    conn.receiveRequestEntity((HttpEntityEnclosingRequest) request);
    HttpEntity entity = ((HttpEntityEnclosingRequest) request)
            .getEntity();
    if (entity != null) {
        // Do something useful with the entity and, when done, ensure all
        // content has been consumed, so that the underlying connection
        // could be re-used
        EntityUtils.consume(entity);
    }
}
HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1,
        200, "OK") ;
response.setEntity(new StringEntity("Got it") );
conn.sendResponseHeader(response);
conn.sendResponseEntity(response);
]]></programlisting>
            <para>
            Please note that one should rarely need to transmit messages using these low level
            methods and should normally use the appropriate higher level HTTP service implementations instead.
            </para>
        </section>
        <section>
            <title>Content transfer with blocking I/O</title>
            <para>
            HTTP connections manage the process of the content transfer using the <interfacename>
            HttpEntity</interfacename> interface. HTTP connections generate an entity object that
            encapsulates the content stream of the incoming message. Please note that <methodname>
            HttpServerConnection#receiveRequestEntity()</methodname> and <methodname>
            HttpClientConnection#receiveResponseEntity()</methodname> do not retrieve or buffer any
            incoming data. They merely inject an appropriate content codec based on the properties
            of the incoming message. The content can be retrieved by reading from the content input
            stream of the enclosed entity using <methodname>HttpEntity#getContent()</methodname>.
            The incoming data will be decoded automatically and completely transparently to the data
            consumer. Likewise, HTTP connections rely on <methodname>
            HttpEntity#writeTo(OutputStream)</methodname> method to generate the content of an
            outgoing message. If an outgoing message encloses an entity, the content will be
            encoded automatically based on the properties of the message.
            </para>
        </section>
        <section>
            <title>Supported content transfer mechanisms</title>
            <para>
            Default implementations of HTTP connections support three content transfer mechanisms
            defined by the HTTP/1.1 specification:
            </para>
            <itemizedlist>
                <listitem>
                    <formalpara>
                    <title><literal>Content-Length</literal> delimited:</title>
                    <para>
                    The end of the content entity is determined by the value of the <literal>
                    Content-Length</literal> header. Maximum entity length: <methodname>
                    Long#MAX_VALUE</methodname>.
                    </para>
                    </formalpara>
                </listitem>
                <listitem>
                    <formalpara>
                    <title>Identity coding:</title>
                    <para>
                    The end of the content entity is demarcated by closing the underlying
                    connection (end of stream condition). For obvious reasons the identity encoding
                    can only be used on the server side. Maximum entity length: unlimited.
                    </para>
                    </formalpara>
                </listitem>
                <listitem>
                    <formalpara>
                    <title>Chunk coding:</title>
                    <para>
                    The content is sent in small chunks. Maximum entity length: unlimited.
                    </para>
                    </formalpara>
                </listitem>
            </itemizedlist>
            <para>
            The appropriate content stream class will be created automatically depending on
            properties of the entity enclosed with the message.
            </para>
        </section>
        <section>
            <title>Terminating HTTP connections</title>
            <para>
            HTTP connections can be terminated either gracefully by calling <methodname>
            HttpConnection#close()</methodname> or forcibly by calling <methodname>
            HttpConnection#shutdown()</methodname>. The former tries to flush all buffered data
            prior to terminating the connection and may block indefinitely. The <methodname>
            HttpConnection#close()</methodname> method is not thread-safe. The latter terminates
            the connection without flushing internal buffers and returns control to the caller as
            soon as possible without blocking for long. The <methodname>HttpConnection#shutdown()
            </methodname> method is thread-safe.
            </para>
        </section>
    </section>
    <section>
        <title>HTTP exception handling</title>
        <para>
        All HttpCore components potentially throw two types of exceptions: <classname>IOException
        </classname>in case of an I/O failure such as socket timeout or an socket reset and
        <classname>HttpException</classname> that signals an HTTP failure such as a violation of
        the HTTP protocol. Usually I/O errors are considered non-fatal and recoverable, whereas
        HTTP protocol errors are considered fatal and cannot be automatically recovered from.
        </para>
        <section>
            <title>Protocol exception</title>
            <para>
            <classname>ProtocolException</classname> signals a fatal HTTP protocol violation that
            usually results in an immediate termination of the HTTP message processing.
            </para>
        </section>
    </section>
    <section>
        <title>Blocking HTTP protocol handlers</title>
        <section>
            <title>HTTP service</title>
            <para>
            <classname>HttpService</classname> is a server side HTTP protocol handler based on the
            blocking I/O model that implements the essential requirements of the HTTP protocol for
            the server side message processing as described by RFC 2616.
            </para>
            <para>
            <classname>HttpService</classname> relies on <interfacename>HttpProcessor
            </interfacename> instance to generate mandatory protocol headers for all outgoing
            messages and apply common, cross-cutting message transformations to all incoming and
            outgoing messages, whereas HTTP request handlers are expected to take care of
            application specific content generation and processing.
            </para>
            <programlisting><![CDATA[
HttpProcessor httpproc = HttpProcessorBuilder.create()
        .add(new ResponseDate())
        .add(new ResponseServer("MyServer-HTTP/1.1"))
        .add(new ResponseContent())
        .add(new ResponseConnControl())
        .build();
HttpService httpService = new HttpService(httpproc, null);
]]></programlisting>
            <section>
                <title>HTTP request handlers</title>
                <para>
                The <interfacename>HttpRequestHandler</interfacename> interface represents a
                routine for processing of a specific group of HTTP requests. <classname>HttpService
                </classname> is designed to take care of protocol specific aspects, whereas
                individual request handlers are expected to take care of application specific HTTP
                processing. The main purpose of a request handler is to generate a response object
                with a content entity to be sent back to the client in response to the given
                request.
                </para>
                <programlisting><![CDATA[
HttpRequestHandler myRequestHandler = new HttpRequestHandler() {

    public void handle(
            HttpRequest request,
            HttpResponse response,
            HttpContext context) throws HttpException, IOException {
        response.setStatusCode(HttpStatus.SC_OK);
        response.setEntity(
                new StringEntity("some important message",
                        ContentType.TEXT_PLAIN));
    }

};
]]></programlisting>
            </section>
            <section>
                <title>Request handler resolver</title>
                <para>
                HTTP request handlers are usually managed by a <interfacename>
                HttpRequestHandlerResolver</interfacename> that matches a request URI to a request
                handler. HttpCore includes a very simple implementation of the request handler
                resolver based on a trivial pattern matching algorithm: <classname>
                HttpRequestHandlerRegistry</classname> supports only three formats:
                <literal>*</literal>, <literal>&lt;uri&gt;*</literal> and
                <literal>*&lt;uri&gt;</literal>.
                </para>
                <programlisting><![CDATA[
HttpProcessor httpproc = <...>

HttpRequestHandler myRequestHandler1 = <...>
HttpRequestHandler myRequestHandler2 = <...>
HttpRequestHandler myRequestHandler3 = <...>

UriHttpRequestHandlerMapper handlerMapper = new UriHttpRequestHandlerMapper();
handlerMapper.register("/service/*", myRequestHandler1);
handlerMapper.register("*.do", myRequestHandler2);
handlerMapper.register("*", myRequestHandler3);
HttpService httpService = new HttpService(httpproc, handlerMapper);
]]></programlisting>
                <para>
                Users are encouraged to provide more sophisticated implementations of
                <interfacename>HttpRequestHandlerResolver</interfacename> - for instance, based on
                regular expressions.
                </para>
            </section>
            <section>
                <title>Using HTTP service to handle requests</title>
                <para>
                When fully initialized and configured, the <classname>HttpService</classname> can
                be used to execute and handle requests for active HTTP connections. The
                <methodname>HttpService#handleRequest()</methodname> method reads an incoming
                request, generates a response and sends it back to the client. This method can be
                executed in a loop to handle multiple requests on a persistent connection. The
                <methodname>HttpService#handleRequest()</methodname> method is safe to execute from
                multiple threads. This allows processing of requests on several connections
                simultaneously, as long as all the protocol interceptors and requests handlers used
                by the <classname>HttpService</classname> are thread-safe.
                </para>
                <programlisting><![CDATA[
HttpService httpService = <...>
HttpServerConnection conn = <...>
HttpContext context = <...>

boolean active = true;
try {
    while (active && conn.isOpen()) {
        httpService.handleRequest(conn, context);
    }
} finally {
    conn.shutdown();
}
]]></programlisting>
            </section>
        </section>
        <section>
            <title>HTTP request executor</title>
            <para>
            <classname>HttpRequestExecutor</classname> is a client side HTTP protocol handler based
            on the blocking I/O model that implements the essential requirements of the HTTP
            protocol for the client side message processing, as described by RFC 2616.
            The <classname>HttpRequestExecutor</classname> relies on the <interfacename>HttpProcessor
            </interfacename> instance to generate mandatory protocol headers for all outgoing
            messages and apply common, cross-cutting message transformations to all incoming and
            outgoing messages. Application specific processing can be implemented outside
            <classname>HttpRequestExecutor</classname> once the request has been executed and a
            response has been received.
            </para>
            <programlisting><![CDATA[
HttpClientConnection conn = <...>

HttpProcessor httpproc = HttpProcessorBuilder.create()
        .add(new RequestContent())
        .add(new RequestTargetHost())
        .add(new RequestConnControl())
        .add(new RequestUserAgent("MyClient/1.1"))
        .add(new RequestExpectContinue(true))
        .build();
HttpRequestExecutor httpexecutor = new HttpRequestExecutor();

HttpRequest request = new BasicHttpRequest("GET", "/");
HttpCoreContext context = HttpCoreContext.create();
httpexecutor.preProcess(request, httpproc, context);
HttpResponse response = httpexecutor.execute(request, conn, context);
httpexecutor.postProcess(response, httpproc, context);

HttpEntity entity = response.getEntity();
EntityUtils.consume(entity);
]]></programlisting>
            <para>
            Methods of <classname>HttpRequestExecutor</classname> are safe to execute from multiple
            threads. This allows execution of requests on several connections simultaneously, as
            long as all the protocol interceptors used by the <classname>HttpRequestExecutor
            </classname> are thread-safe.
            </para>
        </section>
        <section>
            <title>Connection persistence / re-use</title>
            <para>
            The <interfacename>ConnectionReuseStrategy</interfacename> interface is intended to
            determine whether the underlying connection can be re-used for processing of further
            messages after the transmission of the current message has been completed. The default
            connection re-use strategy attempts to keep connections alive whenever possible.
            Firstly, it examines the version of the HTTP protocol used to transmit the message.
            <literal>HTTP/1.1</literal> connections are persistent by default, while <literal>
            HTTP/1.0</literal> connections are not. Secondly, it examines the value of the
            <literal>Connection</literal> header. The peer can indicate whether it intends to
            re-use the connection on the opposite side by sending <literal>Keep-Alive</literal> or
            <literal>Close</literal> values in the <literal>Connection</literal> header. Thirdly,
            the strategy makes the decision whether the connection is safe to re-use based on the
            properties of the enclosed entity, if available.
            </para>
        </section>
    </section>
    <section>
        <title>Connection pools</title>
        <para>
        Efficient client-side HTTP transports often requires effective re-use of persistent
        connections. HttpCore facilitates the process of connection re-use by providing support
        for managing pools of persistent HTTP connections. Connection pool implementations are
        thread-safe and can be used concurrently by multiple consumers.
        </para>
        <para>
        By default the pool allows only 20 concurrent connections in total and two concurrent
        connections per a unique route. The two connection limit is due to the requirements of the
        HTTP specification. However, in practical terms this can often be too restrictive. One can
        change the pool configuration at runtime to allow for more concurrent connections depending
        on a particular application context.
        </para>
        <programlisting><![CDATA[
HttpHost target = new HttpHost("localhost");
BasicConnPool connpool = new BasicConnPool();
connpool.setMaxTotal(200);
connpool.setDefaultMaxPerRoute(10);
connpool.setMaxPerRoute(target, 20);
Future<BasicPoolEntry> future = connpool.lease(target, null);
BasicPoolEntry poolEntry = future.get();
HttpClientConnection conn = poolEntry.getConnection();
]]></programlisting>
        <para>
        Please note that the connection pool has no way of knowing whether or not a leased
        connection is still being used. It is the responsibility of the connection pool user
        to ensure that the connection is released back to the pool once it is not longer needed,
        even if the connection is not reusable.
        </para>
        <programlisting><![CDATA[
BasicConnPool connpool = <...>
Future<BasicPoolEntry> future = connpool.lease(target, null);
BasicPoolEntry poolEntry = future.get();
try {
    HttpClientConnection conn = poolEntry.getConnection();
} finally {
    connpool.release(poolEntry, true);
}
]]></programlisting>
        <para>
        The state of the connection pool can be interrogated at runtime.
        </para>
        <programlisting><![CDATA[
HttpHost target = new HttpHost("localhost");
BasicConnPool connpool = <...>
PoolStats totalStats = connpool.getTotalStats();
System.out.println("total available: " + totalStats.getAvailable());
System.out.println("total leased: " + totalStats.getLeased());
System.out.println("total pending: " + totalStats.getPending());
PoolStats targetStats = connpool.getStats(target);
System.out.println("target available: " + targetStats.getAvailable());
System.out.println("target leased: " + targetStats.getLeased());
System.out.println("target pending: " + targetStats.getPending());
]]></programlisting>
        <para>
        Please note that connection pools do not pro-actively evict expired connections. Even though
        expired connection cannot be leased to the requester, the pool may accumulate stale
        connections over time especially after a period of inactivity. It is generally advisable
        to force eviction of expired and idle connections from the pool after an extensive period
        of inactivity.
        </para>
        <programlisting><![CDATA[
BasicConnPool connpool = <...>
connpool.closeExpired();
connpool.closeIdle(1, TimeUnit.MINUTES);
]]></programlisting>
      <para>
      Generally it is considered to be a responsibility of the consumer to keep track of
      connections leased from the pool and to ensure their immediate release as soon as they
      are no longer needed or actively used. Nevertheless <classname>BasicConnPool </classname>
      provides protected methods to enumerate available idle connections and those currently
      leased from the pool. This enables the pool consumer to query connection state and
      selectively terminate connections meeting a particular criterion.
      </para>
      <programlisting><![CDATA[
static class MyBasicConnPool extends BasicConnPool {

    @Override
    protected void enumAvailable(final PoolEntryCallback<HttpHost, HttpClientConnection> callback) {
        super.enumAvailable(callback);
    }

    @Override
    protected void enumLeased(final PoolEntryCallback<HttpHost, HttpClientConnection> callback) {
        super.enumLeased(callback);
    }

}
]]></programlisting>
      <programlisting><![CDATA[
MyBasicConnPool connpool = new MyBasicConnPool();
connpool.enumAvailable(new PoolEntryCallback<HttpHost, HttpClientConnection>() {

    @Override
    public void process(final PoolEntry<HttpHost, HttpClientConnection> entry) {
        Date creationTime = new Date(entry.getCreated());
        if (creationTime.before(someTime)) {
            entry.close();
        }
    }

});
]]></programlisting>
    </section>
    <section>
        <title>TLS/SSL support</title>
        <para>
        Blocking connections can be bound to any arbitrary socket. This makes SSL support quite
        straight-forward. Any <classname>SSLSocket</classname> instance can be bound to a blocking
        connection in order to make all messages transmitted over than connection secured by
        TLS/SSL.
        </para>
        <programlisting><![CDATA[
SSLContext sslcontext = SSLContexts.createSystemDefault();
SocketFactory sf = sslcontext.getSocketFactory();
SSLSocket socket = (SSLSocket) sf.createSocket("somehost", 443);
// Enforce TLS and disable SSL
socket.setEnabledProtocols(new String[] {
        "TLSv1",
        "TLSv1.1",
        "TLSv1.2" });
// Enforce strong ciphers
socket.setEnabledCipherSuites(new String[] {
        "TLS_RSA_WITH_AES_256_CBC_SHA",
        "TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
        "TLS_DHE_DSS_WITH_AES_256_CBC_SHA" });
DefaultBHttpClientConnection conn = new DefaultBHttpClientConnection(8 * 1204);
conn.bind(socket);
]]></programlisting>
    </section>
  <section>
    <title>Embedded HTTP server</title>
    <para>
    As of version 4.4 HttpCore ships with an embedded HTTP server based on blocking I/O components
    described above.
    </para>
    <programlisting><![CDATA[
HttpRequestHandler requestHandler = <...>
HttpProcessor httpProcessor = <...>
SocketConfig socketConfig = SocketConfig.custom()
        .setSoTimeout(15000)
        .setTcpNoDelay(true)
        .build();
final HttpServer server = ServerBootstrap.bootstrap()
        .setListenerPort(8080)
        .setHttpProcessor(httpProcessor)
        .setSocketConfig(socketConfig)
        .setExceptionLogger(new StdErrorExceptionLogger())
        .registerHandler("*", requestHandler)
        .create();
server.start();
server.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);

Runtime.getRuntime().addShutdownHook(new Thread() {
    @Override
    public void run() {
        server.shutdown(5, TimeUnit.SECONDS);
    }
});
]]></programlisting>
  </section>
</chapter>
