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 2006/11/13 15:31:09 UTC
svn commit: r474333 - in
/jakarta/httpcomponents/httpcore/trunk/module-nio/src:
examples/org/apache/http/nio/examples/ main/java/org/apache/http/nio/impl/
main/java/org/apache/http/nio/protocol/ main/java/org/apache/http/nio/util/
Author: olegk
Date: Mon Nov 13 06:31:08 2006
New Revision: 474333
URL: http://svn.apache.org/viewvc?view=rev&rev=474333
Log:
* Minor API tweaks
* A number of bug fixes
Modified:
jakarta/httpcomponents/httpcore/trunk/module-nio/src/examples/org/apache/http/nio/examples/AsyncHttpServer.java
jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/NHttpConnectionBase.java
jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/protocol/AsyncHttpService.java
jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/util/ContentInputBuffer.java
jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/util/ContentOutputBuffer.java
Modified: jakarta/httpcomponents/httpcore/trunk/module-nio/src/examples/org/apache/http/nio/examples/AsyncHttpServer.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/examples/org/apache/http/nio/examples/AsyncHttpServer.java?view=diff&rev=474333&r1=474332&r2=474333
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/examples/org/apache/http/nio/examples/AsyncHttpServer.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/examples/org/apache/http/nio/examples/AsyncHttpServer.java Mon Nov 13 06:31:08 2006
@@ -10,6 +10,8 @@
import java.net.URLDecoder;
import org.apache.http.ConnectionClosedException;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
@@ -30,6 +32,8 @@
import org.apache.http.nio.protocol.AsyncHttpService;
import org.apache.http.nio.reactor.IOEventDispatch;
import org.apache.http.nio.reactor.IOReactor;
+import org.apache.http.nio.util.ContentInputBuffer;
+import org.apache.http.nio.util.ContentOutputBuffer;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
@@ -41,6 +45,7 @@
import org.apache.http.protocol.ResponseContent;
import org.apache.http.protocol.ResponseDate;
import org.apache.http.protocol.ResponseServer;
+import org.apache.http.util.EntityUtils;
public class AsyncHttpServer {
@@ -52,7 +57,7 @@
HttpParams params = new DefaultHttpParams(null);
params
.setIntParameter(HttpConnectionParams.SO_TIMEOUT, 5000)
- .setIntParameter(HttpConnectionParams.SOCKET_BUFFER_SIZE, 8 * 1024)
+ .setIntParameter(HttpConnectionParams.SOCKET_BUFFER_SIZE, 1024)
.setBooleanParameter(HttpConnectionParams.STALE_CONNECTION_CHECK, false)
.setBooleanParameter(HttpConnectionParams.TCP_NODELAY, true)
.setParameter(HttpProtocolParams.ORIGIN_SERVER, "Jakarta-HttpComponents-NIO/1.1");
@@ -91,12 +96,18 @@
final HttpResponse response,
final HttpContext context) throws HttpException, IOException {
- String method = request.getRequestLine().getMethod();
- if (!method.equalsIgnoreCase("GET") && !method.equalsIgnoreCase("HEAD")) {
+ String method = request.getRequestLine().getMethod().toUpperCase();
+ if (!method.equals("GET") && !method.equals("HEAD") && !method.equals("POST")) {
throw new MethodNotSupportedException(method + " method not supported");
}
- String target = request.getRequestLine().getUri();
+
+ 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()) {
@@ -151,6 +162,7 @@
public static class MyNHttpServiceHandler implements NHttpServiceHandler {
private static final String HTTP_ASYNC_SERVICE = "http.async-service";
+ private static final String HTTP_WORKER_THREAD = "http.worker-thread";
final private HttpRequestHandlerRegistry reqistry;
final private HttpParams params;
@@ -178,9 +190,14 @@
httpproc.addInterceptor(new ResponseContent());
httpproc.addInterceptor(new ResponseConnControl());
+ // Allocate large content input / output buffers
+ ContentInputBuffer inbuffer = new ContentInputBuffer(20480, conn);
+ ContentOutputBuffer outbuffer = new ContentOutputBuffer(20480, conn);
+
// Set up the HTTP service
AsyncHttpService httpService = new AsyncHttpService(
- conn,
+ inbuffer,
+ outbuffer,
httpproc,
new DefaultConnectionReuseStrategy(),
new DefaultHttpResponseFactory());
@@ -223,13 +240,35 @@
}
public void requestReceived(final NHttpServerConnection conn) {
+ HttpRequest request = conn.getHttpRequest();
AsyncHttpService httpService = (AsyncHttpService) conn.getContext()
.getAttribute(HTTP_ASYNC_SERVICE);
+ WorkerThread worker = (WorkerThread) conn.getContext()
+ .getAttribute(HTTP_WORKER_THREAD);
// BIG FAT UGLY WARNING!
- // Do NOT start a new thread per request in real world applications!
- // Do make sure to use a thread pool
- WorkerThread worker = new WorkerThread(httpService, conn);
+ // =====================
+ // (1) This sample application employs an over-simplistic
+ // thread synchronization. In the life applications
+ // consider implementing a proper connection locking
+ // mechanism to ensure that only one worker thread
+ // can have access to an HTTP connection at a time
+ //
+ // (2) Do NOT start a new thread per request in real life
+ // applications! Do make sure to use a thread pool.
+ //
+
+ if (worker != null) {
+ try {
+ worker.join();
+ } catch (InterruptedException ex) {
+ return;
+ }
+ }
+
+ worker = new WorkerThread(httpService, request, conn);
+ conn.getContext().setAttribute(HTTP_WORKER_THREAD, worker);
+
worker.setDaemon(true);
worker.start();
}
@@ -260,31 +299,31 @@
static class WorkerThread extends Thread {
private final AsyncHttpService httpService;
+ private final HttpRequest request;
private final NHttpServerConnection conn;
public WorkerThread(
final AsyncHttpService httpService,
+ final HttpRequest request,
final NHttpServerConnection conn) {
super();
this.httpService = httpService;
+ this.request = request;
this.conn = conn;
}
public void run() {
System.out.println("New request thread");
try {
- this.httpService.handleRequest(this.conn);
+ this.httpService.handleRequest(this.request, this.conn);
} catch (ConnectionClosedException ex) {
System.err.println("Client closed connection");
} catch (IOException ex) {
System.err.println("I/O error: " + ex.getMessage());
} catch (HttpException ex) {
System.err.println("Unrecoverable HTTP protocol violation: " + ex.getMessage());
- } finally {
- try {
- this.conn.shutdown();
- } catch (IOException ignore) {}
}
+ System.out.println("Request thread terminated");
}
}
Modified: jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/NHttpConnectionBase.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/NHttpConnectionBase.java?view=diff&rev=474333&r1=474332&r2=474333
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/NHttpConnectionBase.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/NHttpConnectionBase.java Mon Nov 13 06:31:08 2006
@@ -66,17 +66,17 @@
protected final IOSession session;
protected final HttpContext context;
- protected ContentLengthStrategy incomingContentStrategy;
- protected ContentLengthStrategy outgoingContentStrategy;
+ protected final ContentLengthStrategy incomingContentStrategy;
+ protected final ContentLengthStrategy outgoingContentStrategy;
protected final SessionInputBuffer inbuf;
protected final SessionOutputBuffer outbuf;
protected final CharArrayBuffer lineBuffer;
- protected ContentDecoder contentDecoder;
- protected ContentEncoder contentEncoder;
- protected HttpRequest request;
- protected HttpResponse response;
+ protected volatile ContentDecoder contentDecoder;
+ protected volatile ContentEncoder contentEncoder;
+ protected volatile HttpRequest request;
+ protected volatile HttpResponse response;
protected volatile boolean closed;
@@ -123,19 +123,27 @@
}
public void requestInput() {
- this.session.setEvent(EventMask.READ);
+ if (this.contentEncoder != null) {
+ this.session.setEvent(EventMask.READ);
+ }
}
public void requestOutput() {
- this.session.setEvent(EventMask.WRITE);
+ if (this.contentDecoder != null) {
+ this.session.setEvent(EventMask.WRITE);
+ }
}
public void suspendInput() {
- this.session.clearEvent(EventMask.READ);
+ if (this.contentEncoder != null) {
+ this.session.clearEvent(EventMask.READ);
+ }
}
public void suspendOutput() {
- this.session.clearEvent(EventMask.WRITE);
+ if (this.contentDecoder != null) {
+ this.session.clearEvent(EventMask.WRITE);
+ }
}
protected HttpEntity prepareDecoder(final HttpMessage message) throws HttpException {
Modified: jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/protocol/AsyncHttpService.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/protocol/AsyncHttpService.java?view=diff&rev=474333&r1=474332&r2=474333
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/protocol/AsyncHttpService.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/protocol/AsyncHttpService.java Mon Nov 13 06:31:08 2006
@@ -20,7 +20,6 @@
import org.apache.http.entity.StringEntity;
import org.apache.http.nio.ContentDecoder;
import org.apache.http.nio.ContentEncoder;
-import org.apache.http.nio.ContentIOControl;
import org.apache.http.nio.NHttpServerConnection;
import org.apache.http.nio.util.ContentInputBuffer;
import org.apache.http.nio.util.ContentOutputBuffer;
@@ -43,13 +42,20 @@
private ConnectionReuseStrategy connStrategy = null;
public AsyncHttpService(
- final ContentIOControl ioControl,
+ final ContentInputBuffer inbuffer,
+ final ContentOutputBuffer outbuffer,
final HttpProcessor proc,
final ConnectionReuseStrategy connStrategy,
final HttpResponseFactory responseFactory) {
super();
- this.inbuffer = new ContentInputBuffer(20480, ioControl);
- this.outbuffer = new ContentOutputBuffer(20480, ioControl);
+ if (inbuffer == null) {
+ throw new IllegalArgumentException("Content input buffer may not be null");
+ }
+ if (outbuffer == null) {
+ throw new IllegalArgumentException("Content output buffer may not be null");
+ }
+ this.inbuffer = inbuffer;
+ this.outbuffer = outbuffer;
setHttpProcessor(proc);
setConnReuseStrategy(connStrategy);
setResponseFactory(responseFactory);
@@ -98,14 +104,12 @@
this.outbuffer.shutdown(ex);
}
- public void handleRequest(final NHttpServerConnection conn)
+ public void handleRequest(final HttpRequest request, final NHttpServerConnection conn)
throws HttpException, IOException {
// Reset buffers
this.inbuffer.reset();
this.outbuffer.reset();
- // Get the incoming request
HttpContext parentContext = conn.getContext();
- HttpRequest request = conn.getHttpRequest();
HttpVersion ver = request.getRequestLine().getHttpVersion();
if (!ver.lessEquals(HttpVersion.HTTP_1_1)) {
// Downgrade protocol version if greater than HTTP/1.1
@@ -183,19 +187,10 @@
// Reset buffers
this.inbuffer.reset();
this.outbuffer.reset();
- // Geenrate response
- HttpRequest request = conn.getHttpRequest();
+ // Generate response
HttpContext context = conn.getContext();
- HttpVersion ver = HttpVersion.HTTP_1_1;
- if (request != null) {
- ver = request.getRequestLine().getHttpVersion();
- }
- if (!ver.lessEquals(HttpVersion.HTTP_1_1)) {
- // Downgrade protocol version if greater than HTTP/1.1
- ver = HttpVersion.HTTP_1_1;
- }
-
- HttpResponse response = this.responseFactory.newHttpResponse(ver, HttpStatus.SC_OK);
+ HttpResponse response = this.responseFactory.newHttpResponse(
+ HttpVersion.HTTP_1_0, HttpStatus.SC_OK);
response.getParams().setDefaults(this.params);
if (ex instanceof MethodNotSupportedException) {
Modified: jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/util/ContentInputBuffer.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/util/ContentInputBuffer.java?view=diff&rev=474333&r1=474332&r2=474333
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/util/ContentInputBuffer.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/util/ContentInputBuffer.java Mon Nov 13 06:31:08 2006
@@ -70,7 +70,7 @@
int total = 0;
int bytesRead = 0;
while ((bytesRead = decoder.read(this.buffer)) > 0) {
- total =+ bytesRead;
+ total += bytesRead;
}
if (bytesRead == -1 || decoder.isCompleted()) {
this.endOfStream = true;
Modified: jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/util/ContentOutputBuffer.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/util/ContentOutputBuffer.java?view=diff&rev=474333&r1=474332&r2=474333
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/util/ContentOutputBuffer.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/util/ContentOutputBuffer.java Mon Nov 13 06:31:08 2006
@@ -79,11 +79,11 @@
}
protected void flushBuffer() throws IOException {
- this.ioctrl.requestOutput();
synchronized (this.mutex) {
setOutputMode();
try {
while (hasData() && !this.shutdown) {
+ this.ioctrl.requestOutput();
this.mutex.wait();
}