Index: module-nio/src/test/java/org/apache/http/nio/protocol/TestAsyncNHttpHandlers.java =================================================================== --- module-nio/src/test/java/org/apache/http/nio/protocol/TestAsyncNHttpHandlers.java (revision 632468) +++ module-nio/src/test/java/org/apache/http/nio/protocol/TestAsyncNHttpHandlers.java (working copy) @@ -1277,7 +1277,6 @@ * {@link NHttpResponseTrigger} works correctly. */ public void testDelayedHttpGets() throws Exception { - final int connNo = 3; final int reqNo = 20; final RequestCount requestCount = new RequestCount(connNo * reqNo); @@ -1647,4 +1646,87 @@ } + /** + * This test makes sure that if no service handler is installed, things still work. + */ + public void testNoServiceHandler() throws Exception { + + final int connNo = 3; + final int reqNo = 1; + final RequestCount requestCount = new RequestCount(connNo * reqNo); + + NHttpRequestExecutionHandler requestExecutionHandler = new NHttpRequestExecutionHandler() { + + public void initalizeContext(final HttpContext context, final Object attachment) { + context.setAttribute("REQ-COUNT", new Integer(0)); + context.setAttribute("RES-COUNT", new Integer(0)); + } + + public void finalizeContext(final HttpContext context) { + } + + public HttpRequest submitRequest(final HttpContext context) { + int i = ((Integer) context.getAttribute("REQ-COUNT")).intValue(); + BasicHttpRequest get = null; + if (i < reqNo) { + get = new BasicHttpRequest("GET", "/?" + i); + context.setAttribute("REQ-COUNT", new Integer(i + 1)); + } + return get; + } + + public ConsumingNHttpEntity responseEntity( + final HttpResponse response, + final HttpContext context) throws IOException { + return new BufferingNHttpEntity(response.getEntity(), + new HeapByteBufferAllocator()); + } + + public void handleResponse(final HttpResponse response, final HttpContext context) { + NHttpConnection conn = (NHttpConnection) context.getAttribute( + ExecutionContext.HTTP_CONNECTION); + + int i = ((Integer) context.getAttribute("RES-COUNT")).intValue(); + i++; + context.setAttribute("RES-COUNT", new Integer(i)); + + if(response.getStatusLine().getStatusCode() == 501) + requestCount.decrement(); + else + requestCount.abort(); + + if (i < reqNo) { + conn.requestInput(); + } + } + + }; + + NHttpServiceHandler serviceHandler = createHttpServiceHandler( + null, + null); + + NHttpClientHandler clientHandler = createHttpClientHandler( + requestExecutionHandler); + + this.server.start(serviceHandler); + this.client.start(clientHandler); + + ListenerEndpoint endpoint = this.server.getListenerEndpoint(); + endpoint.waitFor(); + InetSocketAddress serverAddress = (InetSocketAddress) endpoint.getAddress(); + + for (int i = 0; i < connNo; i++) { + this.client.openConnection( + new InetSocketAddress("localhost", serverAddress.getPort()), + null); + } + + requestCount.await(10000); + assertEquals(0, requestCount.getValue()); + + this.client.shutdown(); + this.server.shutdown(); + + } } Index: module-nio/src/main/java/org/apache/http/nio/protocol/AsyncNHttpServiceHandler.java =================================================================== --- module-nio/src/main/java/org/apache/http/nio/protocol/AsyncNHttpServiceHandler.java (revision 632468) +++ module-nio/src/main/java/org/apache/http/nio/protocol/AsyncNHttpServiceHandler.java (working copy) @@ -312,7 +312,7 @@ HttpException httpex = connState.getHttpExepction(); if (httpex != null) { - HttpResponse response = this.responseFactory.newHttpResponse(HttpVersion.HTTP_1_0, + HttpResponse response = this.responseFactory.newHttpResponse(HttpVersion.HTTP_1_0, HttpStatus.SC_INTERNAL_SERVER_ERROR, context); response.setParams( new DefaultedHttpParams(response.getParams(), this.params)); @@ -349,15 +349,16 @@ ProducingNHttpEntity entity = (ProducingNHttpEntity) response.getEntity(); entity.produceContent(encoder, conn); - if (encoder.isCompleted()) { - connState.finishOutput(); + if (encoder.isCompleted()) { + connState.finishOutput(); if (!this.connStrategy.keepAlive(response, context)) { conn.close(); } else { // Ready to process new request connState.reset(); conn.requestInput(); - } + } + responseComplete(conn, response); } } catch (IOException ex) { @@ -405,7 +406,7 @@ NHttpRequestHandler handler = connState.getRequestHandler(); if (handler != null) { - HttpResponse response = this.responseFactory.newHttpResponse( + HttpResponse response = this.responseFactory.newHttpResponse( ver, HttpStatus.SC_OK, context); response.setParams( new DefaultedHttpParams(response.getParams(), this.params)); @@ -416,7 +417,7 @@ trigger, context); } else { - HttpResponse response = this.responseFactory.newHttpResponse(ver, + HttpResponse response = this.responseFactory.newHttpResponse(ver, HttpStatus.SC_NOT_IMPLEMENTED, context); response.setParams( new DefaultedHttpParams(response.getParams(), this.params)); @@ -451,18 +452,29 @@ if (entity != null) { ProducingNHttpEntity producingEntity = (ProducingNHttpEntity) entity; connState.setProducingEntity(producingEntity); - } else { + } + + conn.submitResponse(response); + + if(entity == null) { if (!this.connStrategy.keepAlive(response, context)) { conn.close(); } else { // Ready to process new request connState.reset(); conn.requestInput(); - } + } + responseComplete(conn, response); } - - conn.submitResponse(response); } + + /** + * Signals that this response has been fully sent. This will be called after + * submitting the response to a connection, if there is no entity in the + * response. If there is an entity, it will be called after the entity has + * completed. + */ + protected void responseComplete(NHttpServerConnection conn, HttpResponse response) {} private NHttpRequestHandler getRequestHandler(HttpRequest request) { NHttpRequestHandler handler = null;