Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 86397200CD7 for ; Tue, 1 Aug 2017 19:28:52 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id 84E661667B9; Tue, 1 Aug 2017 17:28:52 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id CA78D166892 for ; Tue, 1 Aug 2017 19:28:51 +0200 (CEST) Received: (qmail 74856 invoked by uid 500); 1 Aug 2017 17:28:51 -0000 Mailing-List: contact commits-help@hc.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: "HttpComponents Project" Delivered-To: mailing list commits@hc.apache.org Received: (qmail 74777 invoked by uid 99); 1 Aug 2017 17:28:50 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 01 Aug 2017 17:28:50 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 5D22DF3252; Tue, 1 Aug 2017 17:28:50 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: olegk@apache.org To: commits@hc.apache.org Date: Tue, 01 Aug 2017 17:28:52 -0000 Message-Id: <419ee2a2568742fea7e75ae73cc2019b@git.apache.org> In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [3/3] httpcomponents-client git commit: [HTTPCLIENT-1865] DefaultServiceUnavailableRetryStrategy does not respect HttpEntity#isRepeatable. archived-at: Tue, 01 Aug 2017 17:28:52 -0000 [HTTPCLIENT-1865] DefaultServiceUnavailableRetryStrategy does not respect HttpEntity#isRepeatable. Project: http://git-wip-us.apache.org/repos/asf/httpcomponents-client/repo Commit: http://git-wip-us.apache.org/repos/asf/httpcomponents-client/commit/9efcba87 Tree: http://git-wip-us.apache.org/repos/asf/httpcomponents-client/tree/9efcba87 Diff: http://git-wip-us.apache.org/repos/asf/httpcomponents-client/diff/9efcba87 Branch: refs/heads/master Commit: 9efcba87302dc76fe31b33d685bca1fea34cf7f2 Parents: f2146ca Author: Tomas Celaya Authored: Mon Jul 31 18:10:03 2017 -0700 Committer: Oleg Kalnichevski Committed: Tue Aug 1 19:25:17 2017 +0200 ---------------------------------------------------------------------- .../impl/sync/ServiceUnavailableRetryExec.java | 5 +++ .../sync/TestServiceUnavailableRetryExec.java | 32 ++++++++++++++++++++ 2 files changed, 37 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/httpcomponents-client/blob/9efcba87/httpclient5/src/main/java/org/apache/hc/client5/http/impl/sync/ServiceUnavailableRetryExec.java ---------------------------------------------------------------------- diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/sync/ServiceUnavailableRetryExec.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/sync/ServiceUnavailableRetryExec.java index 42fcff3..721f98d 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/sync/ServiceUnavailableRetryExec.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/sync/ServiceUnavailableRetryExec.java @@ -39,6 +39,7 @@ import org.apache.hc.core5.annotation.Contract; import org.apache.hc.core5.annotation.ThreadingBehavior; import org.apache.hc.core5.http.ClassicHttpRequest; import org.apache.hc.core5.http.ClassicHttpResponse; +import org.apache.hc.core5.http.HttpEntity; import org.apache.hc.core5.http.HttpException; import org.apache.hc.core5.util.Args; import org.apache.logging.log4j.LogManager; @@ -82,6 +83,10 @@ final class ServiceUnavailableRetryExec implements ExecChainHandler { for (int c = 1;; c++) { final ClassicHttpResponse response = chain.proceed(currentRequest, scope); try { + final HttpEntity entity = request.getEntity(); + if (entity != null && !entity.isRepeatable()) { + return response; + } if (this.retryStrategy.retryRequest(response, c, context)) { response.close(); final long nextInterval = this.retryStrategy.getRetryInterval(response, context); http://git-wip-us.apache.org/repos/asf/httpcomponents-client/blob/9efcba87/httpclient5/src/test/java/org/apache/hc/client5/http/impl/sync/TestServiceUnavailableRetryExec.java ---------------------------------------------------------------------- diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/sync/TestServiceUnavailableRetryExec.java b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/sync/TestServiceUnavailableRetryExec.java index 60b8fd3..1ce4920 100644 --- a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/sync/TestServiceUnavailableRetryExec.java +++ b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/sync/TestServiceUnavailableRetryExec.java @@ -26,17 +26,22 @@ */ package org.apache.hc.client5.http.impl.sync; +import java.io.ByteArrayInputStream; + import org.apache.hc.client5.http.HttpRoute; +import org.apache.hc.client5.http.entity.EntityBuilder; import org.apache.hc.client5.http.protocol.HttpClientContext; import org.apache.hc.client5.http.sync.ExecChain; import org.apache.hc.client5.http.sync.ExecRuntime; import org.apache.hc.client5.http.sync.ServiceUnavailableRetryStrategy; import org.apache.hc.client5.http.sync.methods.HttpGet; +import org.apache.hc.client5.http.sync.methods.HttpPost; import org.apache.hc.core5.http.ClassicHttpRequest; import org.apache.hc.core5.http.ClassicHttpResponse; import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.HttpResponse; import org.apache.hc.core5.http.protocol.HttpContext; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; @@ -113,4 +118,31 @@ public class TestServiceUnavailableRetryExec { throw ex; } } + + @Test + public void testNonRepeatableEntityResponseReturnedImmediately() throws Exception { + final HttpRoute route = new HttpRoute(target); + + final HttpPost request = new HttpPost("/test"); + request.setEntity(EntityBuilder.create() + .setStream(new ByteArrayInputStream(new byte[]{})) + .build()); + final HttpClientContext context = HttpClientContext.create(); + + final ClassicHttpResponse response = Mockito.mock(ClassicHttpResponse.class); + Mockito.when(chain.proceed( + Mockito.any(), + Mockito.any())).thenReturn(response); + Mockito.when(retryStrategy.retryRequest( + Mockito.any(), + Mockito.anyInt(), + Mockito.any())).thenReturn(Boolean.TRUE, Boolean.FALSE); + + final ExecChain.Scope scope = new ExecChain.Scope(route, request, endpoint, context); + final ClassicHttpResponse finalResponse = retryExec.execute(request, scope, chain); + + Assert.assertSame(response, finalResponse); + Mockito.verify(response, Mockito.times(0)).close(); + } + }