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 2007/02/22 16:00:20 UTC
svn commit: r510540 - in
/jakarta/httpcomponents/httpcore/trunk/module-nio/src:
main/java/org/apache/http/impl/nio/ main/java/org/apache/http/nio/
main/java/org/apache/http/nio/protocol/
test/java/org/apache/http/nio/mockup/ test/java/org/apache/http/n...
Author: olegk
Date: Thu Feb 22 07:00:14 2007
New Revision: 510540
URL: http://svn.apache.org/viewvc?view=rev&rev=510540
Log:
HTTPCORE-42:
* Introduced methods to cancel pending entity enclosing HTTP request in case of the target server expectation failure to both client and server NHttpConnection interfaces
* Added more test cases
Modified:
jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/DefaultNHttpClientConnection.java
jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/DefaultNHttpServerConnection.java
jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/NHttpClientConnection.java
jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/NHttpServerConnection.java
jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/protocol/BufferingHttpClientHandler.java
jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/protocol/BufferingHttpServiceHandler.java
jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/nio/mockup/TestHttpServer.java
jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/nio/protocol/TestNIOHttp.java
Modified: jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/DefaultNHttpClientConnection.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/DefaultNHttpClientConnection.java?view=diff&rev=510540&r1=510539&r2=510540
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/DefaultNHttpClientConnection.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/DefaultNHttpClientConnection.java Thu Feb 22 07:00:14 2007
@@ -194,4 +194,8 @@
return this.request != null;
}
+ public void cancelRequest() {
+ resetOutput();
+ }
+
}
Modified: jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/DefaultNHttpServerConnection.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/DefaultNHttpServerConnection.java?view=diff&rev=510540&r1=510539&r2=510540
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/DefaultNHttpServerConnection.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/DefaultNHttpServerConnection.java Thu Feb 22 07:00:14 2007
@@ -194,4 +194,8 @@
return this.response != null;
}
+ public void cancelRequest() {
+ resetInput();
+ }
+
}
Modified: jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/NHttpClientConnection.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/NHttpClientConnection.java?view=diff&rev=510540&r1=510539&r2=510540
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/NHttpClientConnection.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/NHttpClientConnection.java Thu Feb 22 07:00:14 2007
@@ -59,4 +59,11 @@
*/
boolean isRequestSubmitted();
+ /**
+ * Cancels pending HTTP request if it failed the target server expections
+ * (the target server responded with non 1xx status code during the
+ * 'expect: continue' handshake.
+ */
+ void cancelRequest();
+
}
Modified: jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/NHttpServerConnection.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/NHttpServerConnection.java?view=diff&rev=510540&r1=510539&r2=510540
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/NHttpServerConnection.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/NHttpServerConnection.java Thu Feb 22 07:00:14 2007
@@ -60,4 +60,11 @@
*/
boolean isResponseSubmitted();
+ /**
+ * Cancels pending HTTP request if it failed the target server expections
+ * (the target server responded with non 1xx status code during the
+ * 'expect: continue' handshake).
+ */
+ void cancelRequest();
+
}
Modified: jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/protocol/BufferingHttpClientHandler.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/protocol/BufferingHttpClientHandler.java?view=diff&rev=510540&r1=510539&r2=510540
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/protocol/BufferingHttpClientHandler.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/protocol/BufferingHttpClientHandler.java Thu Feb 22 07:00:14 2007
@@ -274,6 +274,10 @@
} else {
connState.setResponse(response);
connState.setInputState(ClientConnState.RESPONSE_RECEIVED);
+
+ if (connState.getOutputState() == ClientConnState.EXPECT_CONTINUE) {
+ cancelRequest(conn, connState);
+ }
}
if (!canResponseHaveBody(request, response)) {
@@ -376,6 +380,17 @@
prepareRequestBody((HttpEntityEnclosingRequest) request, connState);
conn.requestOutput();
connState.setOutputState(ClientConnState.REQUEST_SENT);
+ }
+
+ private void cancelRequest(
+ final NHttpClientConnection conn,
+ final ClientConnState connState) throws IOException {
+
+ int timeout = connState.getTimeout();
+ conn.setSocketTimeout(timeout);
+
+ conn.cancelRequest();
+ connState.resetOutput();
}
private void prepareRequestBody(
Modified: jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/protocol/BufferingHttpServiceHandler.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/protocol/BufferingHttpServiceHandler.java?view=diff&rev=510540&r1=510539&r2=510540
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/protocol/BufferingHttpServiceHandler.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/protocol/BufferingHttpServiceHandler.java Thu Feb 22 07:00:14 2007
@@ -193,6 +193,8 @@
conn.submitResponse(response);
} else {
// The request does not meet the server expections
+ conn.cancelRequest();
+ connState.resetInput();
sendResponse(conn, response);
}
}
Modified: jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/nio/mockup/TestHttpServer.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/nio/mockup/TestHttpServer.java?view=diff&rev=510540&r1=510539&r2=510540
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/nio/mockup/TestHttpServer.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/nio/mockup/TestHttpServer.java Thu Feb 22 07:00:14 2007
@@ -45,6 +45,7 @@
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.BasicHttpProcessor;
+import org.apache.http.protocol.HttpExpectationVerifier;
import org.apache.http.protocol.HttpRequestHandler;
import org.apache.http.protocol.HttpRequestHandlerRegistry;
import org.apache.http.protocol.ResponseConnControl;
@@ -60,6 +61,7 @@
public class TestHttpServer extends TestHttpServiceBase {
private final HttpRequestHandlerRegistry reqistry;
+ private HttpExpectationVerifier expectationVerifier;
private volatile SocketAddress address;
private final Object mutex;
@@ -83,6 +85,10 @@
this.reqistry.register(pattern, handler);
}
+ public void setExpectationVerifier(final HttpExpectationVerifier expectationVerifier) {
+ this.expectationVerifier = expectationVerifier;
+ }
+
protected void execute() throws IOException {
synchronized (this.mutex) {
this.address = ((ListeningIOReactor) this.ioReactor).listen(new InetSocketAddress(0));
@@ -101,7 +107,7 @@
this.params);
serviceHandler.setEventListener(new EventLogger());
-
+ serviceHandler.setExpectationVerifier(this.expectationVerifier);
serviceHandler.setHandlerResolver(this.reqistry);
IOEventDispatch ioEventDispatch = new DefaultServerIOEventDispatch(
Modified: jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/nio/protocol/TestNIOHttp.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/nio/protocol/TestNIOHttp.java?view=diff&rev=510540&r1=510539&r2=510540
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/nio/protocol/TestNIOHttp.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/nio/protocol/TestNIOHttp.java Thu Feb 22 07:00:14 2007
@@ -38,11 +38,13 @@
import java.util.List;
import java.util.Random;
+import org.apache.http.Header;
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;
+import org.apache.http.HttpStatus;
import org.apache.http.HttpVersion;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.StringEntity;
@@ -55,7 +57,9 @@
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpExecutionContext;
+import org.apache.http.protocol.HttpExpectationVerifier;
import org.apache.http.protocol.HttpRequestHandler;
+import org.apache.http.util.EncodingUtils;
import org.apache.http.util.EntityUtils;
import junit.framework.Test;
@@ -220,8 +224,8 @@
this.client.await(connNo, 1000);
assertEquals(connNo, this.client.getConnCount());
- this.server.await(connNo, 1000);
- assertEquals(connNo, this.server.getConnCount());
+ this.client.shutdown();
+ this.server.shutdown();
for (int c = 0; c < responseData.length; c++) {
List receivedPackets = responseData[c];
@@ -363,8 +367,8 @@
this.client.await(connNo, 1000);
assertEquals(connNo, this.client.getConnCount());
- this.server.await(connNo, 1000);
- assertEquals(connNo, this.server.getConnCount());
+ this.client.shutdown();
+ this.server.shutdown();
for (int c = 0; c < responseData.length; c++) {
List receivedPackets = responseData[c];
@@ -507,8 +511,8 @@
this.client.await(connNo, 1000);
assertEquals(connNo, this.client.getConnCount());
- this.server.await(connNo, 1000);
- assertEquals(connNo, this.server.getConnCount());
+ this.client.shutdown();
+ this.server.shutdown();
for (int c = 0; c < responseData.length; c++) {
List receivedPackets = responseData[c];
@@ -654,8 +658,8 @@
this.client.await(connNo, 1000);
assertEquals(connNo, this.client.getConnCount());
- this.server.await(connNo, 1000);
- assertEquals(connNo, this.server.getConnCount());
+ this.client.shutdown();
+ this.server.shutdown();
for (int c = 0; c < responseData.length; c++) {
List receivedPackets = responseData[c];
@@ -800,8 +804,8 @@
this.client.await(connNo, 1000);
assertEquals(connNo, this.client.getConnCount());
- this.server.await(connNo, 1000);
- assertEquals(connNo, this.server.getConnCount());
+ this.client.shutdown();
+ this.server.shutdown();
for (int c = 0; c < responseData.length; c++) {
List receivedPackets = responseData[c];
@@ -820,5 +824,142 @@
}
+ /**
+ * This test case executes a series of simple (non-pipelined) POST requests
+ * over multiple connections that do not meet the target server expectations.
+ */
+ public void testHttpPostsWithExpectationVerification() throws Exception {
+
+ final int reqNo = 3;
+ final List responses = new ArrayList(reqNo);
+
+ // Initialize the server-side request handler
+ this.server.registerHandler("*", new HttpRequestHandler() {
+
+ public void handle(
+ final HttpRequest request,
+ final HttpResponse response,
+ final HttpContext context) throws HttpException, IOException {
+
+ StringEntity outgoing = new StringEntity("No content");
+ response.setEntity(outgoing);
+ }
+
+ });
+
+ this.server.setExpectationVerifier(new HttpExpectationVerifier() {
+
+ public void verify(
+ final HttpRequest request,
+ final HttpResponse response,
+ final HttpContext context) throws HttpException {
+ Header someheader = request.getFirstHeader("Secret");
+ if (someheader != null) {
+ int secretNumber;
+ try {
+ secretNumber = Integer.parseInt(someheader.getValue());
+ } catch (NumberFormatException ex) {
+ response.setStatusCode(HttpStatus.SC_BAD_REQUEST);
+ return;
+ }
+ if (secretNumber < 2) {
+ response.setStatusCode(HttpStatus.SC_EXPECTATION_FAILED);
+ ByteArrayEntity outgoing = new ByteArrayEntity(
+ EncodingUtils.getAsciiBytes("Wrong secret number"));
+ response.setEntity(outgoing);
+ }
+ }
+ }
+
+ });
+
+ // Activate 'expect: continue' handshake
+ this.client.getParams().setBooleanParameter(HttpProtocolParams.USE_EXPECT_CONTINUE, true);
+ // Initialize the client side request executor
+ this.client.setHttpRequestExecutionHandler(new HttpRequestExecutionHandler() {
+
+ public void initalizeContext(final HttpContext context, final Object attachment) {
+ context.setAttribute("LIST", (List) attachment);
+ context.setAttribute("STATUS", "ready");
+ }
+
+ public HttpRequest submitRequest(final HttpContext context) {
+ NHttpConnection conn = (NHttpConnection) context.getAttribute(
+ HttpExecutionContext.HTTP_CONNECTION);
+ String status = (String) context.getAttribute("STATUS");
+ if (!status.equals("ready")) {
+ return null;
+ }
+ int index = 0;
+
+ Integer intobj = (Integer) context.getAttribute("INDEX");
+ if (intobj != null) {
+ index = intobj.intValue();
+ }
+
+ HttpPost post = null;
+ if (index < reqNo) {
+ post = new HttpPost("/");
+ post.addHeader("Secret", Integer.toString(index));
+ ByteArrayEntity outgoing = new ByteArrayEntity(
+ EncodingUtils.getAsciiBytes("No content"));
+ post.setEntity(outgoing);
+
+ context.setAttribute("INDEX", new Integer(index + 1));
+ context.setAttribute("STATUS", "busy");
+ } else {
+ try {
+ conn.close();
+ } catch (IOException ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ return post;
+ }
+
+ public void handleResponse(final HttpResponse response, final HttpContext context) {
+ NHttpConnection conn = (NHttpConnection) context.getAttribute(
+ HttpExecutionContext.HTTP_CONNECTION);
+
+ HttpEntity entity = response.getEntity();
+ if (entity != null) {
+ try {
+ entity.consumeContent();
+ } catch (IOException ex) {
+ fail(ex.getMessage());
+ }
+ }
+
+ List list = (List) context.getAttribute("LIST");
+ list.add(response);
+ context.setAttribute("STATUS", "ready");
+ conn.requestInput();
+ }
+
+ });
+
+ this.server.start();
+ this.client.start();
+
+ InetSocketAddress serverAddress = (InetSocketAddress) this.server.getSocketAddress();
+
+ this.client.openConnection(
+ new InetSocketAddress("localhost", serverAddress.getPort()),
+ responses);
+
+ this.client.await(1, 1000);
+
+ this.client.shutdown();
+ this.server.shutdown();
+
+ assertEquals(reqNo, responses.size());
+ HttpResponse response = (HttpResponse) responses.get(0);
+ assertEquals(HttpStatus.SC_EXPECTATION_FAILED, response.getStatusLine().getStatusCode());
+ response = (HttpResponse) responses.get(1);
+ assertEquals(HttpStatus.SC_EXPECTATION_FAILED, response.getStatusLine().getStatusCode());
+ response = (HttpResponse) responses.get(2);
+ assertEquals(HttpStatus.SC_OK, response.getStatusLine().getStatusCode());
+ }
}