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());
- }
-
- }
-
}