You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2011/09/06 11:14:51 UTC

svn commit: r1165575 - in /httpcomponents/httpcore/trunk/httpcore-nio/src/examples/org/apache/http/examples/nio: NHttpClient.java NHttpSSLClient.java NHttpSSLServer.java NHttpServer.java

Author: olegk
Date: Tue Sep  6 09:14:50 2011
New Revision: 1165575

URL: http://svn.apache.org/viewvc?rev=1165575&view=rev
Log:
Updated NIO client and server examples

Modified:
    httpcomponents/httpcore/trunk/httpcore-nio/src/examples/org/apache/http/examples/nio/NHttpClient.java
    httpcomponents/httpcore/trunk/httpcore-nio/src/examples/org/apache/http/examples/nio/NHttpSSLClient.java
    httpcomponents/httpcore/trunk/httpcore-nio/src/examples/org/apache/http/examples/nio/NHttpSSLServer.java
    httpcomponents/httpcore/trunk/httpcore-nio/src/examples/org/apache/http/examples/nio/NHttpServer.java

Modified: httpcomponents/httpcore/trunk/httpcore-nio/src/examples/org/apache/http/examples/nio/NHttpClient.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore-nio/src/examples/org/apache/http/examples/nio/NHttpClient.java?rev=1165575&r1=1165574&r2=1165575&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore-nio/src/examples/org/apache/http/examples/nio/NHttpClient.java (original)
+++ httpcomponents/httpcore/trunk/httpcore-nio/src/examples/org/apache/http/examples/nio/NHttpClient.java Tue Sep  6 09:14:50 2011
@@ -29,29 +29,27 @@ package org.apache.http.examples.nio;
 import java.io.IOException;
 import java.io.InterruptedIOException;
 import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
 
 import org.apache.http.HttpHost;
-import org.apache.http.HttpRequest;
 import org.apache.http.HttpRequestInterceptor;
 import org.apache.http.HttpResponse;
 import org.apache.http.concurrent.FutureCallback;
 import org.apache.http.impl.DefaultConnectionReuseStrategy;
 import org.apache.http.impl.nio.DefaultClientIODispatch;
 import org.apache.http.impl.nio.pool.BasicNIOConnPool;
-import org.apache.http.impl.nio.pool.BasicNIOPoolEntry;
 import org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor;
 import org.apache.http.message.BasicHttpRequest;
-import org.apache.http.nio.NHttpClientConnection;
-import org.apache.http.nio.protocol.BufferingHttpClientHandler;
-import org.apache.http.nio.protocol.HttpRequestExecutionHandler;
+import org.apache.http.nio.protocol.BasicAsyncRequestProducer;
+import org.apache.http.nio.protocol.BasicAsyncResponseConsumer;
+import org.apache.http.nio.protocol.HttpAsyncClientProtocolHandler;
+import org.apache.http.nio.protocol.HttpAsyncRequestExecutor;
 import org.apache.http.nio.reactor.ConnectingIOReactor;
 import org.apache.http.nio.reactor.IOEventDispatch;
 import org.apache.http.params.CoreConnectionPNames;
 import org.apache.http.params.CoreProtocolPNames;
 import org.apache.http.params.HttpParams;
 import org.apache.http.params.SyncBasicHttpParams;
-import org.apache.http.protocol.HttpContext;
+import org.apache.http.protocol.BasicHttpContext;
 import org.apache.http.protocol.HttpProcessor;
 import org.apache.http.protocol.ImmutableHttpProcessor;
 import org.apache.http.protocol.RequestConnControl;
@@ -62,48 +60,43 @@ import org.apache.http.protocol.RequestU
 
 /**
  * Elemental example for executing HTTP requests using the non-blocking I/O model.
- * <p>
- * Please note the purpose of this application is demonstrate the usage of HttpCore APIs.
- * It is NOT intended to demonstrate the most efficient way of building an HTTP client.
  */
 public class NHttpClient {
 
     public static void main(String[] args) throws Exception {
-        final ConnectingIOReactor ioReactor = new DefaultConnectingIOReactor();
+        // HTTP parameters for the client
         HttpParams params = new SyncBasicHttpParams();
         params
-            .setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 5000)
-            .setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 10000)
+            .setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 3000)
+            .setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 3000)
             .setIntParameter(CoreConnectionPNames.SOCKET_BUFFER_SIZE, 8 * 1024)
-            .setBooleanParameter(CoreConnectionPNames.STALE_CONNECTION_CHECK, false)
             .setBooleanParameter(CoreConnectionPNames.TCP_NODELAY, true)
             .setParameter(CoreProtocolPNames.USER_AGENT, "Test/1.1");
-
-
-        BasicNIOConnPool pool = new BasicNIOConnPool(ioReactor, params);
-        // Limit total number of connections to just two
-        pool.setDefaultMaxPerRoute(2);
-        pool.setMaxTotal(2);
-
+        // Create HTTP protocol processing chain
         HttpProcessor httpproc = new ImmutableHttpProcessor(new HttpRequestInterceptor[] {
+                // Use standard client-side protocol interceptors
                 new RequestContent(),
                 new RequestTargetHost(),
                 new RequestConnControl(),
                 new RequestUserAgent(),
                 new RequestExpectContinue()});
-
-        BufferingHttpClientHandler handler = new BufferingHttpClientHandler(
-                httpproc,
-                new MyHttpRequestExecutionHandler(),
-                new DefaultConnectionReuseStrategy(),
-                params);
-
-        final IOEventDispatch ioEventDispatch = new DefaultClientIODispatch(handler, params);
-
+        // Create client-side HTTP protocol handler
+        HttpAsyncClientProtocolHandler protocolHandler = new HttpAsyncClientProtocolHandler();
+        // Create client-side I/O event dispatch
+        final IOEventDispatch ioEventDispatch = new DefaultClientIODispatch(protocolHandler, params);
+        // Create client-side I/O reactor
+        final ConnectingIOReactor ioReactor = new DefaultConnectingIOReactor();
+        // Create HTTP connection pool
+        BasicNIOConnPool pool = new BasicNIOConnPool(ioReactor, params);
+        // Limit total number of connections to just two
+        pool.setDefaultMaxPerRoute(2);
+        pool.setMaxTotal(2);
+        // Run the I/O reactor in a separate thread
         Thread t = new Thread(new Runnable() {
 
             public void run() {
                 try {
+                    // Ready to go!
                     ioReactor.execute(ioEventDispatch);
                 } catch (InterruptedIOException ex) {
                     System.err.println("Interrupted");
@@ -114,116 +107,49 @@ public class NHttpClient {
             }
 
         });
+        // Start the client thread
         t.start();
+        // Create HTTP request executor
+        HttpAsyncRequestExecutor executor = new HttpAsyncRequestExecutor(
+                httpproc, new DefaultConnectionReuseStrategy(), params);
+        // Execute HTTP GETs to the following hosts and
+        HttpHost[] targets = new HttpHost[] {
+                new HttpHost("www.apache.org", 80, "http"),
+                new HttpHost("www.verisign.com", 443, "https"),
+                new HttpHost("www.google.com", 80, "http")
+        };
+        final CountDownLatch latch = new CountDownLatch(targets.length);
+        for (final HttpHost target: targets) {
+            BasicHttpRequest request = new BasicHttpRequest("GET", "/");
+            executor.execute(
+                    new BasicAsyncRequestProducer(target, request),
+                    new BasicAsyncResponseConsumer(),
+                    pool,
+                    new BasicHttpContext(),
+                    // Handle HTTP response from a callback
+                    new FutureCallback<HttpResponse>() {
+
+                public void completed(final HttpResponse response) {
+                    latch.countDown();
+                    System.out.println(target + "->" + response.getStatusLine());
+                }
 
-        CountDownLatch requestCount = new CountDownLatch(3);
+                public void failed(final Exception ex) {
+                    latch.countDown();
+                    System.out.println(target + "->" + ex);
+                }
 
-        pool.lease(new HttpHost("www.google.com", 80), null,
-                new AsyncRequestExecutor(new BasicHttpRequest("GET", "/"), pool, requestCount));
-        pool.lease(new HttpHost("www.yahoo.com", 80), null,
-                new AsyncRequestExecutor(new BasicHttpRequest("GET", "/"), pool, requestCount));
-        pool.lease(new HttpHost("www.apache.org", 80), null,
-                new AsyncRequestExecutor(new BasicHttpRequest("GET", "/"), pool, requestCount));
-
-        // Block until all connections signal
-        // completion of the request execution
-        requestCount.await(30, TimeUnit.SECONDS);
+                public void cancelled() {
+                    latch.countDown();
+                    System.out.println(target + " cancelled");
+                }
 
+            });
+        }
+        latch.await();
         System.out.println("Shutting down I/O reactor");
-
         ioReactor.shutdown();
-
         System.out.println("Done");
     }
 
-    static class AsyncRequestExecutor implements FutureCallback<BasicNIOPoolEntry> {
-
-        private final HttpRequest request;
-        private final BasicNIOConnPool pool;
-        private final CountDownLatch requestCount;
-        private volatile BasicNIOPoolEntry poolEntry;
-        private volatile boolean completed;
-
-        AsyncRequestExecutor(
-                final HttpRequest request,
-                final BasicNIOConnPool pool,
-                final CountDownLatch requestCount) {
-            super();
-            this.request = request;
-            this.pool = pool;
-            this.requestCount = requestCount;
-        }
-
-        public void failed(final Exception ex) {
-            this.requestCount.countDown();
-            System.out.println("Connection request failed: " + ex.getMessage());
-        }
-
-        public void cancelled() {
-            this.requestCount.countDown();
-            System.out.println("Connection cancelled failed");
-        }
-
-        public void completed(final BasicNIOPoolEntry entry) {
-            this.poolEntry = entry;
-            NHttpClientConnection conn = entry.getConnection();
-            conn.getContext().setAttribute("executor", this);
-            conn.requestOutput();
-            System.out.println(this.poolEntry.getRoute() + ": obtained connection from the pool");
-        }
-
-        public HttpRequest getRequest() {
-            System.out.println(this.poolEntry.getRoute() + ": sending request " + this.request.getRequestLine());
-            return this.request;
-        }
-
-        public void handleResponse(final HttpResponse response) {
-            if (this.completed) {
-                return;
-            }
-            System.out.println(this.poolEntry.getRoute() + ": received response " + response.getStatusLine());
-            this.completed = true;
-            this.requestCount.countDown();
-            this.pool.release(this.poolEntry, false);
-        }
-
-        public void shutdown() {
-            if (this.completed) {
-                return;
-            }
-            this.completed = true;
-            this.requestCount.countDown();
-            this.pool.release(this.poolEntry, false);
-        }
-
-    };
-
-    static class MyHttpRequestExecutionHandler implements HttpRequestExecutionHandler {
-
-        public MyHttpRequestExecutionHandler() {
-            super();
-        }
-
-        public void initalizeContext(final HttpContext context, final Object attachment) {
-        }
-
-        public void finalizeContext(final HttpContext context) {
-            AsyncRequestExecutor executor = (AsyncRequestExecutor) context.getAttribute("executor");
-            if (executor != null) {
-                executor.shutdown();
-            }
-        }
-
-        public HttpRequest submitRequest(final HttpContext context) {
-            AsyncRequestExecutor executor = (AsyncRequestExecutor) context.getAttribute("executor");
-            return executor.getRequest();
-        }
-
-        public void handleResponse(final HttpResponse response, final HttpContext context) {
-            AsyncRequestExecutor executor = (AsyncRequestExecutor) context.getAttribute("executor");
-            executor.handleResponse(response);
-        }
-
-    }
-
 }

Modified: httpcomponents/httpcore/trunk/httpcore-nio/src/examples/org/apache/http/examples/nio/NHttpServer.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore-nio/src/examples/org/apache/http/examples/nio/NHttpServer.java?rev=1165575&r1=1165574&r2=1165575&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore-nio/src/examples/org/apache/http/examples/nio/NHttpServer.java (original)
+++ httpcomponents/httpcore/trunk/httpcore-nio/src/examples/org/apache/http/examples/nio/NHttpServer.java Tue Sep  6 09:14:50 2011
@@ -30,52 +30,62 @@ import java.io.File;
 import java.io.IOException;
 import java.io.InterruptedIOException;
 import java.net.InetSocketAddress;
+import java.net.URL;
 import java.net.URLDecoder;
+import java.security.KeyStore;
 import java.util.Locale;
 
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpEntityEnclosingRequest;
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+
 import org.apache.http.HttpException;
 import org.apache.http.HttpRequest;
 import org.apache.http.HttpResponse;
+import org.apache.http.HttpResponseFactory;
 import org.apache.http.HttpResponseInterceptor;
 import org.apache.http.HttpStatus;
+import org.apache.http.HttpVersion;
 import org.apache.http.MethodNotSupportedException;
+import org.apache.http.ProtocolVersion;
 import org.apache.http.entity.ContentType;
 import org.apache.http.impl.DefaultConnectionReuseStrategy;
 import org.apache.http.impl.DefaultHttpResponseFactory;
+import org.apache.http.impl.nio.DefaultNHttpServerConnectionFactory;
 import org.apache.http.impl.nio.DefaultServerIODispatch;
+import org.apache.http.impl.nio.SSLNHttpServerConnectionFactory;
 import org.apache.http.impl.nio.reactor.DefaultListeningIOReactor;
 import org.apache.http.nio.NHttpConnection;
+import org.apache.http.nio.NHttpConnectionFactory;
+import org.apache.http.nio.NHttpServerConnection;
+import org.apache.http.nio.NHttpServerIOTarget;
 import org.apache.http.nio.entity.NFileEntity;
 import org.apache.http.nio.entity.NStringEntity;
-import org.apache.http.nio.protocol.BufferingHttpServiceHandler;
-import org.apache.http.nio.protocol.EventListener;
+import org.apache.http.nio.protocol.BasicAsyncRequestConsumer;
+import org.apache.http.nio.protocol.BasicAsyncResponseProducer;
+import org.apache.http.nio.protocol.HttpAsyncRequestConsumer;
+import org.apache.http.nio.protocol.HttpAsyncRequestHandler;
+import org.apache.http.nio.protocol.HttpAsyncRequestHandlerRegistry;
+import org.apache.http.nio.protocol.HttpAsyncResponseTrigger;
+import org.apache.http.nio.protocol.HttpAsyncServiceHandler;
 import org.apache.http.nio.reactor.IOEventDispatch;
 import org.apache.http.nio.reactor.ListeningIOReactor;
 import org.apache.http.params.CoreConnectionPNames;
 import org.apache.http.params.CoreProtocolPNames;
 import org.apache.http.params.HttpParams;
 import org.apache.http.params.SyncBasicHttpParams;
+import org.apache.http.protocol.ExecutionContext;
 import org.apache.http.protocol.HttpContext;
 import org.apache.http.protocol.HttpProcessor;
-import org.apache.http.protocol.HttpRequestHandler;
-import org.apache.http.protocol.HttpRequestHandlerRegistry;
 import org.apache.http.protocol.ImmutableHttpProcessor;
 import org.apache.http.protocol.ResponseConnControl;
 import org.apache.http.protocol.ResponseContent;
 import org.apache.http.protocol.ResponseDate;
 import org.apache.http.protocol.ResponseServer;
-import org.apache.http.util.EntityUtils;
 
 /**
  * Basic, yet fully functional and spec compliant, HTTP/1.1 server based on the non-blocking
  * I/O model.
- * <p>
- * Please note the purpose of this application is demonstrate the usage of HttpCore APIs.
- * It is NOT intended to demonstrate the most efficient way of building an HTTP server.
- *
- *
  */
 public class NHttpServer {
 
@@ -84,40 +94,78 @@ public class NHttpServer {
             System.err.println("Please specify document root directory");
             System.exit(1);
         }
+        // Document root directory
+        File docRoot = new File(args[0]);
+        int port = 8080;
+        if (args.length >= 2) {
+            port = Integer.parseInt(args[1]);
+        }
+        // HTTP parameters for the server
         HttpParams params = new SyncBasicHttpParams();
         params
             .setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 5000)
             .setIntParameter(CoreConnectionPNames.SOCKET_BUFFER_SIZE, 8 * 1024)
-            .setBooleanParameter(CoreConnectionPNames.STALE_CONNECTION_CHECK, false)
             .setBooleanParameter(CoreConnectionPNames.TCP_NODELAY, true)
-            .setParameter(CoreProtocolPNames.ORIGIN_SERVER, "HttpComponents/1.1");
-
+            .setParameter(CoreProtocolPNames.ORIGIN_SERVER, "HttpTest/1.1");
+        // Create HTTP protocol processing chain
         HttpProcessor httpproc = new ImmutableHttpProcessor(new HttpResponseInterceptor[] {
+                // Use standard server-side protocol interceptors
                 new ResponseDate(),
                 new ResponseServer(),
                 new ResponseContent(),
                 new ResponseConnControl()
         });
+        // Create request handler registry
+        HttpAsyncRequestHandlerRegistry reqistry = new HttpAsyncRequestHandlerRegistry();
+        // Register the default handler for all URIs
+        reqistry.register("*", new HttpFileHandler(docRoot));
+        // Create server-side HTTP protocol handler
+        HttpAsyncServiceHandler protocolHandler = new HttpAsyncServiceHandler(
+                reqistry, httpproc, new DefaultConnectionReuseStrategy(), params) {
+
+            @Override
+            public void connected(final NHttpServerConnection conn) {
+                System.out.println(conn + ": connection open");
+                super.connected(conn);
+            }
 
-        BufferingHttpServiceHandler handler = new BufferingHttpServiceHandler(
-                httpproc,
-                new DefaultHttpResponseFactory(),
-                new DefaultConnectionReuseStrategy(),
-                params);
-
-        // Set up request handlers
-        HttpRequestHandlerRegistry reqistry = new HttpRequestHandlerRegistry();
-        reqistry.register("*", new HttpFileHandler(args[0]));
-
-        handler.setHandlerResolver(reqistry);
-
-        // Provide an event logger
-        handler.setEventListener(new EventLogger());
+            @Override
+            public void closed(final NHttpServerConnection conn) {
+                System.out.println(conn + ": connection closed");
+                super.closed(conn);
+            }
 
-        IOEventDispatch ioEventDispatch = new DefaultServerIODispatch(handler, params);
+        };
+        // Create HTTP connection factory
+        NHttpConnectionFactory<NHttpServerIOTarget> connFactory;
+        if (port == 8443) {
+            // Initialize SSL context
+            ClassLoader cl = NHttpServer.class.getClassLoader();
+            URL url = cl.getResource("my.keystore");
+            if (url == null) {
+                System.out.println("Keystore not found");
+                System.exit(1);
+            }
+            KeyStore keystore  = KeyStore.getInstance("jks");
+            keystore.load(url.openStream(), "secret".toCharArray());
+            KeyManagerFactory kmfactory = KeyManagerFactory.getInstance(
+                    KeyManagerFactory.getDefaultAlgorithm());
+            kmfactory.init(keystore, "secret".toCharArray());
+            KeyManager[] keymanagers = kmfactory.getKeyManagers();
+            SSLContext sslcontext = SSLContext.getInstance("TLS");
+            sslcontext.init(keymanagers, null, null);
+            connFactory = new SSLNHttpServerConnectionFactory(sslcontext, null, params);
+        } else {
+            connFactory = new DefaultNHttpServerConnectionFactory(params);
+        }
+        // Create server-side I/O event dispatch
+        IOEventDispatch ioEventDispatch = new DefaultServerIODispatch(protocolHandler, connFactory);
+        // Create server-side I/O reactor
         ListeningIOReactor ioReactor = new DefaultListeningIOReactor();
         try {
-            ioReactor.listen(new InetSocketAddress(8080));
+            // Listen of the given port
+            ioReactor.listen(new InetSocketAddress(port));
+            // Ready to go!
             ioReactor.execute(ioEventDispatch);
         } catch (InterruptedIOException ex) {
             System.err.println("Interrupted");
@@ -127,17 +175,39 @@ public class NHttpServer {
         System.out.println("Shutdown");
     }
 
-    static class HttpFileHandler implements HttpRequestHandler  {
+    static class HttpFileHandler implements HttpAsyncRequestHandler<HttpRequest> {
 
-        private final String docRoot;
+        private final File docRoot;
+        private final HttpResponseFactory responseFactory;
 
-        public HttpFileHandler(final String docRoot) {
+        public HttpFileHandler(final File docRoot) {
             super();
             this.docRoot = docRoot;
+            this.responseFactory = new DefaultHttpResponseFactory();
+        }
+
+        public HttpAsyncRequestConsumer<HttpRequest> processRequest(
+                final HttpRequest request,
+                final HttpContext context) {
+            // Buffer request content in memory for simplicity
+            return new BasicAsyncRequestConsumer();
         }
 
         public void handle(
                 final HttpRequest request,
+                final HttpAsyncResponseTrigger trigger,
+                final HttpContext context) throws HttpException, IOException {
+            ProtocolVersion ver = request.getRequestLine().getProtocolVersion();
+            if (!ver.lessEquals(HttpVersion.HTTP_1_1)) {
+                ver = HttpVersion.HTTP_1_1;
+            }
+            HttpResponse response = this.responseFactory.newHttpResponse(ver, HttpStatus.SC_OK, context);
+            handleInternal(request, response, context);
+            trigger.submitResponse(new BasicAsyncResponseProducer(response));
+        }
+
+        private void handleInternal(
+                final HttpRequest request,
                 final HttpResponse response,
                 final HttpContext context) throws HttpException, IOException {
 
@@ -146,12 +216,6 @@ public class NHttpServer {
                 throw new MethodNotSupportedException(method + " method not supported");
             }
 
-            if (request instanceof HttpEntityEnclosingRequest) {
-                HttpEntity entity = ((HttpEntityEnclosingRequest) request).getEntity();
-                byte[] entityContent = EntityUtils.toByteArray(entity);
-                System.out.println("Incoming entity content (bytes): " + entityContent.length);
-            }
-
             String target = request.getRequestLine().getUri();
             final File file = new File(this.docRoot, URLDecoder.decode(target, "UTF-8"));
             if (!file.exists()) {
@@ -174,38 +238,15 @@ public class NHttpServer {
                 System.out.println("Cannot read file " + file.getPath());
 
             } else {
-
+                NHttpConnection conn = (NHttpConnection) context.getAttribute(
+                        ExecutionContext.HTTP_CONNECTION);
                 response.setStatusCode(HttpStatus.SC_OK);
                 NFileEntity body = new NFileEntity(file, ContentType.create("text/html", null));
                 response.setEntity(body);
-                System.out.println("Serving file " + file.getPath());
+                System.out.println(conn + ": serving file " + file.getPath());
             }
         }
 
     }
 
-    static class EventLogger implements EventListener {
-
-        public void connectionOpen(final NHttpConnection conn) {
-            System.out.println("Connection open: " + conn);
-        }
-
-        public void connectionTimeout(final NHttpConnection conn) {
-            System.out.println("Connection timed out: " + conn);
-        }
-
-        public void connectionClosed(final NHttpConnection conn) {
-            System.out.println("Connection closed: " + conn);
-        }
-
-        public void fatalIOException(final IOException ex, final NHttpConnection conn) {
-            System.err.println("I/O error: " + ex.getMessage());
-        }
-
-        public void fatalProtocolException(final HttpException ex, final NHttpConnection conn) {
-            System.err.println("HTTP error: " + ex.getMessage());
-        }
-
-    }
-
 }