Index: /home/oleg/src/apache.org/jakarta-httpcomponents/http-core/src/examples/org/apache/http/examples/ElementalHttpGet.java =================================================================== --- /home/oleg/src/apache.org/jakarta-httpcomponents/http-core/src/examples/org/apache/http/examples/ElementalHttpGet.java (revision 357063) +++ /home/oleg/src/apache.org/jakarta-httpcomponents/http-core/src/examples/org/apache/http/examples/ElementalHttpGet.java (working copy) @@ -57,7 +57,7 @@ Scheme.registerScheme("http", new Scheme("http", socketfactory, 80)); HttpParams connparams = new DefaultHttpParams(null); - HttpHost host = new HttpHost("www.yahoo.com"); + HttpHost host = new HttpHost("localhost", 8080); HttpClientConnection conn = new DefaultHttpClientConnection(host); try { @@ -63,7 +63,7 @@ String[] targets = { "/", - "/news/", + "/servlets-examples/servlet/RequestInfoExample", "/somewhere%20in%20pampa"}; for (int i = 0; i < targets.length; i++) { @@ -78,13 +78,8 @@ System.out.println("Connection kept alive. Reusing..."); } System.out.println(">> Request URI: " + request.getRequestLine().getUri()); - HttpResponse response = conn.sendRequest(request); - // Request may be terminated prematurely, when expect-continue - // protocol is used - if (response == null) { - // No error response so far. - response = conn.receiveResponse(request); - } + conn.sendRequest(request); + HttpResponse response = conn.receiveResponse(request.getParams()); System.out.println("<< Response: " + response.getStatusLine()); System.out.println(EntityUtils.toString(response.getEntity())); System.out.println("=============="); Index: /home/oleg/src/apache.org/jakarta-httpcomponents/http-core/src/examples/org/apache/http/examples/ElementalHttpPost.java =================================================================== --- /home/oleg/src/apache.org/jakarta-httpcomponents/http-core/src/examples/org/apache/http/examples/ElementalHttpPost.java (revision 357063) +++ /home/oleg/src/apache.org/jakarta-httpcomponents/http-core/src/examples/org/apache/http/examples/ElementalHttpPost.java (working copy) @@ -79,7 +79,7 @@ }; for (int i = 0; i < requestBodies.length; i++) { - HttpPost request = new HttpPost("/httpclienttest/body"); + HttpPost request = new HttpPost("/servlets-examples/servlet/RequestInfoExample"); request.setHeader(new Header("Host", host.toHostString())); request.setHeader(new Header("User-Agent", "Elemental HTTP client")); request.setHeader(new Header("Connection", "Keep-Alive")); @@ -105,13 +105,8 @@ System.out.println("Connection kept alive. Reusing..."); } System.out.println(">> Request URI: " + request.getRequestLine().getUri()); - HttpResponse response = conn.sendRequest(request); - // Request may be terminated prematurely, when expect-continue - // protocol is used - if (response == null) { - // No error response so far. - response = conn.receiveResponse(request); - } + conn.sendRequest(request); + HttpResponse response = conn.receiveResponse(request.getParams()); System.out.println("<< Response: " + response.getStatusLine()); System.out.println(EntityUtils.toString(response.getEntity())); System.out.println("=============="); Index: /home/oleg/src/apache.org/jakarta-httpcomponents/http-core/src/java/org/apache/http/HttpClientConnection.java =================================================================== --- /home/oleg/src/apache.org/jakarta-httpcomponents/http-core/src/java/org/apache/http/HttpClientConnection.java (revision 357063) +++ /home/oleg/src/apache.org/jakarta-httpcomponents/http-core/src/java/org/apache/http/HttpClientConnection.java (working copy) @@ -55,8 +55,14 @@ void open(HttpParams params) throws IOException; - HttpResponse sendRequest(HttpRequest request) throws HttpException, IOException; + void sendRequest(HttpRequest request) throws HttpException, IOException; + + void sendRequestHeader(HttpEntityEnclosingRequest request) throws HttpException, IOException; - HttpResponse receiveResponse(HttpRequest request) throws HttpException, IOException; + void sendRequestEntity(HttpEntityEnclosingRequest request) throws HttpException, IOException; + + HttpResponse receiveResponse(HttpParams params) throws HttpException, IOException; + + HttpResponse receiveResponse(HttpParams params, int timeout) throws HttpException, IOException; } Index: /home/oleg/src/apache.org/jakarta-httpcomponents/http-core/src/java/org/apache/http/executor/HttpRequestExecutor.java =================================================================== --- /home/oleg/src/apache.org/jakarta-httpcomponents/http-core/src/java/org/apache/http/executor/HttpRequestExecutor.java (revision 357063) +++ /home/oleg/src/apache.org/jakarta-httpcomponents/http-core/src/java/org/apache/http/executor/HttpRequestExecutor.java (working copy) @@ -30,8 +30,11 @@ package org.apache.http.executor; import java.io.IOException; +import java.net.ProtocolException; +import org.apache.http.Header; import org.apache.http.HttpClientConnection; +import org.apache.http.HttpEntityEnclosingRequest; import org.apache.http.HttpException; import org.apache.http.HttpMutableRequest; import org.apache.http.HttpMutableResponse; @@ -37,6 +40,8 @@ import org.apache.http.HttpMutableResponse; import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.HttpVersion; import org.apache.http.params.HttpConnectionParams; import org.apache.http.params.HttpParams; import org.apache.http.protocol.AbstractHttpProcessor; @@ -53,6 +58,10 @@ */ public class HttpRequestExecutor extends AbstractHttpProcessor { + private static final String EXPECT_DIRECTIVE = "Expect"; + private static final String EXPECT_CONTINUE = "100-Continue"; + private static final int WAIT_FOR_CONTINUE_MS = 10000; + private HttpParams params = null; private HttpRequestRetryHandler retryhandler = null; @@ -95,7 +104,6 @@ } HttpResponse response = null; - // loop until the method is successfully processed, the retryHandler // returns false or a non-recoverable exception is thrown for (int execCount = 0; ; execCount++) { @@ -111,14 +119,44 @@ } localContext.setAttribute(HttpExecutionContext.HTTP_REQ_SENT, new Boolean(false)); - response = conn.sendRequest(request); + HttpVersion ver = request.getRequestLine().getHttpVersion(); + Header expect = request.getFirstHeader(EXPECT_DIRECTIVE); + + if (expect != null + && EXPECT_CONTINUE.equalsIgnoreCase(expect.getValue()) + && ver.greaterEquals(HttpVersion.HTTP_1_1) + && request instanceof HttpEntityEnclosingRequest) { + // Do 'expect: continue' handshake + conn.sendRequestHeader((HttpEntityEnclosingRequest)request); + response = conn.receiveResponse(request.getParams(), + WAIT_FOR_CONTINUE_MS); + if (response == null) { + // No response. The 'expect: continue' is likely not supported + break; + } + int status = response.getStatusLine().getStatusCode(); + if (status < 200) { + if (status != HttpStatus.SC_CONTINUE) { + throw new ProtocolException("Unexpected response: " + + response.getStatusLine()); + } + } else { + break; + } + conn.sendRequestEntity((HttpEntityEnclosingRequest)request); + } else { + // Just fire and forget + conn.sendRequest(request); + } localContext.setAttribute(HttpExecutionContext.HTTP_REQ_SENT, new Boolean(true)); - // Request may be terminated prematurely, if the expect-continue - // protocol is used - if (response == null) { - // No error response so far. - response = conn.receiveResponse(request); + for (;;) { + // Loop until non 1xx resposne is received + response = conn.receiveResponse(request.getParams()); + int statuscode = response.getStatusLine().getStatusCode(); + if (statuscode >= HttpStatus.SC_OK) { + break; + } } break; } catch (IOException ex) { Index: /home/oleg/src/apache.org/jakarta-httpcomponents/http-core/src/java/org/apache/http/impl/DefaultHttpClientConnection.java =================================================================== --- /home/oleg/src/apache.org/jakarta-httpcomponents/http-core/src/java/org/apache/http/impl/DefaultHttpClientConnection.java (revision 357063) +++ /home/oleg/src/apache.org/jakarta-httpcomponents/http-core/src/java/org/apache/http/impl/DefaultHttpClientConnection.java (working copy) @@ -45,7 +45,6 @@ import org.apache.http.HttpResponse; import org.apache.http.HttpResponseFactory; import org.apache.http.HttpStatus; -import org.apache.http.HttpVersion; import org.apache.http.NoHttpResponseException; import org.apache.http.ProtocolException; import org.apache.http.RequestLine; @@ -71,10 +70,6 @@ public class DefaultHttpClientConnection extends AbstractHttpConnection implements HttpClientConnection { - private static final String EXPECT_DIRECTIVE = "Expect"; - private static final String EXPECT_CONTINUE = "100-Continue"; - private static final int WAIT_FOR_CONTINUE_MS = 10000; - private HttpHost targethost = null; private InetAddress localAddress = null; @@ -149,7 +144,7 @@ super.close(); } - public HttpResponse sendRequest(final HttpRequest request) + public void sendRequest(final HttpRequest request) throws HttpException, IOException { if (request == null) { throw new IllegalArgumentException("HTTP request may not be null"); @@ -160,21 +155,38 @@ sendRequestLine(request); sendRequestHeaders(request); - if (request instanceof HttpEntityEnclosingRequest) { - // send request may be prematurely terminated by the target server - HttpResponse response = expectContinue(request); - if (response != null) { - return response; - } sendRequestBody((HttpEntityEnclosingRequest)request); } this.datatransmitter.flush(); - return null; + } + + public void sendRequestHeader(final HttpEntityEnclosingRequest request) + throws HttpException, IOException { + if (request == null) { + throw new IllegalArgumentException("HTTP request may not be null"); + } + assertOpen(); + // reset the data transmitter + this.datatransmitter.reset(request.getParams()); + + sendRequestLine(request); + sendRequestHeaders(request); + this.datatransmitter.flush(); + } + + public void sendRequestEntity(final HttpEntityEnclosingRequest request) + throws HttpException, IOException { + if (request == null) { + throw new IllegalArgumentException("HTTP request may not be null"); + } + sendRequestBody(request); + this.datatransmitter.flush(); } + - protected void sendRequestLine( - final HttpRequest request) throws HttpException, IOException { + protected void sendRequestLine(final HttpRequest request) + throws HttpException, IOException { this.buffer.clear(); RequestLine.format(this.buffer, request.getRequestLine()); this.datatransmitter.writeLine(this.buffer); @@ -183,8 +195,8 @@ } } - protected void sendRequestHeaders( - final HttpRequest request) throws HttpException, IOException { + protected void sendRequestHeaders(final HttpRequest request) + throws HttpException, IOException { Header[] headers = request.getAllHeaders(); for (int i = 0; i < headers.length; i++) { this.buffer.clear(); @@ -201,33 +213,6 @@ } } - protected HttpResponse expectContinue(final HttpRequest request) - throws HttpException, IOException { - // See if 'expect-continue' handshake is supported - HttpVersion ver = request.getRequestLine().getHttpVersion(); - if (ver.greaterEquals(HttpVersion.HTTP_1_1)) { - // ... and activated - Header expect = request.getFirstHeader(EXPECT_DIRECTIVE); - if (expect != null && EXPECT_CONTINUE.equalsIgnoreCase(expect.getValue())) { - // flush the headers - this.datatransmitter.flush(); - if (this.datareceiver.isDataAvailable(WAIT_FOR_CONTINUE_MS)) { - HttpResponse response = readResponse(request); - int status = response.getStatusLine().getStatusCode(); - if (status < 200) { - if (status != HttpStatus.SC_CONTINUE) { - throw new ProtocolException("Unexpected response: " + - response.getStatusLine()); - } - } else { - return response; - } - } - } - } - return null; - } - protected void sendRequestBody(final HttpEntityEnclosingRequest request) throws HttpException, IOException { if (request.getEntity() == null) { @@ -240,35 +225,39 @@ this.datatransmitter); } - public HttpResponse receiveResponse(final HttpRequest request) - throws HttpException, IOException { - if (request == null) { - throw new IllegalArgumentException("HTTP request may not be null"); + public HttpResponse receiveResponse(final HttpParams params) + throws HttpException, IOException { + if (params == null) { + throw new IllegalArgumentException("HTTP parameters may not be null"); } assertOpen(); + // reset the data receiver + this.datareceiver.reset(params); + return readResponse(params); + } + public HttpResponse receiveResponse(final HttpParams params, int timeout) + throws HttpException, IOException { + if (params == null) { + throw new IllegalArgumentException("HTTP parameters may not be null"); + } + assertOpen(); // reset the data receiver - this.datareceiver.reset(request.getParams()); - - for (;;) { - HttpResponse response = readResponse(request); - int statuscode = response.getStatusLine().getStatusCode(); - if (statuscode >= 200) { - return response; - } - if (isWarnEnabled()) { - warn("Unexpected provisional response: " + response.getStatusLine()); - } + this.datareceiver.reset(params); + if (this.datareceiver.isDataAvailable(timeout)) { + return readResponse(params); + } else { + return null; } } - protected HttpResponse readResponse(final HttpRequest request) + protected HttpResponse readResponse(final HttpParams params) throws HttpException, IOException { - this.datareceiver.reset(request.getParams()); - HttpMutableResponse response = readResponseStatusLine(request.getParams()); + this.datareceiver.reset(params); + HttpMutableResponse response = readResponseStatusLine(params); readResponseHeaders(response); ResponseStrategy responsestrategy = new DefaultResponseStrategy(); - if (responsestrategy.canHaveEntity(request, response)) { + if (responsestrategy.canHaveEntity(null, response)) { readResponseBody(response); } return response; Index: /home/oleg/src/apache.org/jakarta-httpcomponents/http-core/src/java/org/apache/http/impl/DefaultResponseStrategy.java =================================================================== --- /home/oleg/src/apache.org/jakarta-httpcomponents/http-core/src/java/org/apache/http/impl/DefaultResponseStrategy.java (revision 357063) +++ /home/oleg/src/apache.org/jakarta-httpcomponents/http-core/src/java/org/apache/http/impl/DefaultResponseStrategy.java (working copy) @@ -51,15 +51,14 @@ } public boolean canHaveEntity(final HttpRequest request, final HttpResponse response) { - if (request == null) { - throw new IllegalArgumentException("HTTP request may not be null"); - } if (response == null) { throw new IllegalArgumentException("HTTP response may not be null"); } - String method = request.getRequestLine().getMethod(); - if (HEAD_METHOD.equalsIgnoreCase(method)) { - return false; + if (request != null) { + String method = request.getRequestLine().getMethod(); + if (HEAD_METHOD.equalsIgnoreCase(method)) { + return false; + } } int status = response.getStatusLine().getStatusCode(); if (status < HttpStatus.SC_OK) {