Index: httpclient/src/main/java/org/apache/http/impl/client/DefaultHttpRequestRetryHandler.java =================================================================== --- httpclient/src/main/java/org/apache/http/impl/client/DefaultHttpRequestRetryHandler.java (revision 1059221) +++ httpclient/src/main/java/org/apache/http/impl/client/DefaultHttpRequestRetryHandler.java (working copy) @@ -33,12 +33,13 @@ import java.net.UnknownHostException; import javax.net.ssl.SSLException; +import org.apache.http.HttpEntity; import org.apache.http.annotation.Immutable; import org.apache.http.HttpEntityEnclosingRequest; -import org.apache.http.HttpRequest; import org.apache.http.client.HttpRequestRetryHandler; +import org.apache.http.client.methods.HttpPost; import org.apache.http.protocol.HttpContext; import org.apache.http.protocol.ExecutionContext; @@ -54,16 +55,20 @@ /** the number of times a method will be retried */ private final int retryCount; - /** Whether or not methods that have successfully sent their request will be retried */ - private final boolean requestSentRetryEnabled; + /** + * Whether or not all the methods defined as idempotent in + * RFC-2616 section 9.1.2 (GET, HEAD, PUT, DELETE, OPTIONS, and TRACE) + * should be assumed to be idempotent and retried + */ + private final boolean retryIdempotentMethodsEnabled; /** * Default constructor */ - public DefaultHttpRequestRetryHandler(int retryCount, boolean requestSentRetryEnabled) { + public DefaultHttpRequestRetryHandler(int retryCount, boolean retryIdempotentMethodsEnabled) { super(); this.retryCount = retryCount; - this.requestSentRetryEnabled = requestSentRetryEnabled; + this.retryIdempotentMethodsEnabled = retryIdempotentMethodsEnabled; } /** @@ -73,7 +78,8 @@ this(3, false); } /** - * Used retryCount and requestSentRetryEnabled to determine + * Used retryCount and + * retryIdempotentMethodsEnabled to determine * if the given method should be retried. */ public boolean retryRequest( @@ -107,33 +113,50 @@ return false; } - HttpRequest request = (HttpRequest) - context.getAttribute(ExecutionContext.HTTP_REQUEST); - boolean idempotent = !(request instanceof HttpEntityEnclosingRequest); - if (idempotent) { - // Retry if the request is considered idempotent + Boolean b = (Boolean)context.getAttribute(ExecutionContext.HTTP_REQ_SENT); + boolean sent = (b != null && b.booleanValue()); + if (!sent) { + // Retry if the request has not been sent fully return true; } - Boolean b = (Boolean) - context.getAttribute(ExecutionContext.HTTP_REQ_SENT); - boolean sent = (b != null && b.booleanValue()); + // Consider retrying idempotent Methods? + if (!this.retryIdempotentMethodsEnabled) { + return false; + } - if (!sent || this.requestSentRetryEnabled) { - // Retry if the request has not been sent fully or - // if it's OK to retry methods that have been sent + Object requestObj = context.getAttribute(ExecutionContext.HTTP_REQUEST); + if (requestObj instanceof HttpEntityEnclosingRequest) { + HttpEntityEnclosingRequest request = (HttpEntityEnclosingRequest)requestObj; + HttpEntity entity = request.getEntity(); + + if (entity != null && !entity.isRepeatable()) { + // Don't retry if we can't resend the enclosed HttpEntity anyway + return false; + } + } + + // From the current list of supported HTTP methods: + // GET, HEAD, POST, PUT, DELETE, OPTIONS, and TRACE + // RFC-2616 section 9.1.2 declares the following should be idempotent: + // GET, HEAD, PUT, DELETE, OPTIONS, and TRACE + boolean idempotent = !(requestObj instanceof HttpPost); + if (idempotent) { + // Retry if the request is considered idempotent return true; } + // otherwise do not retry return false; } /** - * @return true if this handler will retry methods that have - * successfully sent their request, false otherwise + * @return true if this handler will attempt to retry + * GET, HEAD, PUT, DELETE, OPTIONS, and TRACE methods that were + * already sent, false otherwise */ - public boolean isRequestSentRetryEnabled() { - return requestSentRetryEnabled; + public boolean isRetryIdempotentMethodsEnabled() { + return retryIdempotentMethodsEnabled; } /**