Skip to content

Commit

Permalink
HTTPCLIENT-951: Non-repeatable entity enclosing requests are not corr…
Browse files Browse the repository at this point in the history
…ectly retried when 'expect-continue' handshake is active

git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.0.x@957015 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
ok2c committed Jun 22, 2010
1 parent ed18d9e commit ef067cb
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 6 deletions.
4 changes: 4 additions & 0 deletions RELEASE_NOTES.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
Changes since 4.0.1
-------------------

* [HTTPCLIENT-951] Non-repeatable entity enclosing requests are not correctly
retried when 'expect-continue' handshake is active.
Contributed by Oleg Kalnichevski <olegk at apache.org>

* [HTTPCLIENT-953] IllegalStateException thrown by RouteSpecificPool.
Contributed by Guillaume <gueugaie at gmail.com>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,7 @@ public HttpResponse execute(HttpHost target, HttpRequest request,
execCount++;
// Increment exec count for this particular request
wrapper.incrementExecCount();
if (wrapper.getExecCount() > 1 && !wrapper.isRepeatable()) {
if (!wrapper.isRepeatable()) {
this.log.debug("Cannot retry non-repeatable request");
if (retryReason != null) {
throw new NonRepeatableRequestException("Cannot retry request " +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,12 @@

package org.apache.http.impl.client;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import org.apache.http.annotation.NotThreadSafe;
import org.apache.http.entity.HttpEntityWrapper;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
Expand All @@ -51,19 +56,21 @@ public class EntityEnclosingRequestWrapper extends RequestWrapper
implements HttpEntityEnclosingRequest {

private HttpEntity entity;
private boolean consumed;

public EntityEnclosingRequestWrapper(final HttpEntityEnclosingRequest request)
public EntityEnclosingRequestWrapper(final HttpEntityEnclosingRequest request)
throws ProtocolException {
super(request);
this.entity = request.getEntity();
setEntity(request.getEntity());
}

public HttpEntity getEntity() {
return this.entity;
}

public void setEntity(final HttpEntity entity) {
this.entity = entity;
this.entity = entity != null ? new EntityWrapper(entity) : null;
this.consumed = false;
}

public boolean expectContinue() {
Expand All @@ -73,7 +80,33 @@ public boolean expectContinue() {

@Override
public boolean isRepeatable() {
return this.entity == null || this.entity.isRepeatable();
return this.entity == null || this.entity.isRepeatable() || !this.consumed;
}

class EntityWrapper extends HttpEntityWrapper {

EntityWrapper(final HttpEntity entity) {
super(entity);
}

@Override
public void consumeContent() throws IOException {
consumed = true;
super.consumeContent();
}

@Override
public InputStream getContent() throws IOException {
consumed = true;
return super.getContent();
}

@Override
public void writeTo(final OutputStream outstream) throws IOException {
consumed = true;
super.writeTo(outstream);
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -658,12 +658,13 @@ public HttpResponse execute(
final HttpClientConnection conn,
final HttpContext context) throws IOException, HttpException {

HttpResponse response = super.execute(request, conn, context);
Object marker = context.getAttribute(MARKER);
if (marker == null) {
context.setAttribute(MARKER, Boolean.TRUE);
throw new IOException(failureMsg);
}
return super.execute(request, conn, context);
return response;
}

}
Expand Down Expand Up @@ -744,6 +745,16 @@ public void testNonRepeatableEntity() throws Exception {
String failureMsg = "a message showing that this failed";

FaultyHttpClient client = new FaultyHttpClient(failureMsg);
client.setHttpRequestRetryHandler(new HttpRequestRetryHandler() {

public boolean retryRequest(
final IOException exception,
int executionCount,
final HttpContext context) {
return true;
}

});
HttpContext context = new BasicHttpContext();

String s = "http://localhost:" + port;
Expand Down

0 comments on commit ef067cb

Please sign in to comment.