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 2015/06/27 12:50:13 UTC

svn commit: r1687907 - in /httpcomponents/httpclient/trunk/httpclient/src: main/java/org/apache/http/client/ main/java/org/apache/http/impl/client/ main/java/org/apache/http/impl/execchain/ test/java/org/apache/http/impl/client/ test/java/org/apache/ht...

Author: olegk
Date: Sat Jun 27 10:50:12 2015
New Revision: 1687907

URL: http://svn.apache.org/r1687907
Log:
RFC 7231: DefaultServiceUnavailableRetryStrategy to take Retry-After header value into account if specified

Added:
    httpcomponents/httpclient/trunk/httpclient/src/test/java/org/apache/http/impl/client/TestDefaultServiceUnavailableRetryStrategy.java   (with props)
Modified:
    httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/client/ServiceUnavailableRetryStrategy.java
    httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/client/DefaultServiceUnavailableRetryStrategy.java
    httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/execchain/ServiceUnavailableRetryExec.java
    httpcomponents/httpclient/trunk/httpclient/src/test/java/org/apache/http/impl/execchain/TestServiceUnavailableRetryExec.java

Modified: httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/client/ServiceUnavailableRetryStrategy.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/client/ServiceUnavailableRetryStrategy.java?rev=1687907&r1=1687906&r2=1687907&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/client/ServiceUnavailableRetryStrategy.java (original)
+++ httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/client/ServiceUnavailableRetryStrategy.java Sat Jun 27 10:50:12 2015
@@ -53,8 +53,8 @@ public interface ServiceUnavailableRetry
     boolean retryRequest(HttpResponse response, int executionCount, HttpContext context);
 
     /**
-     * @return The interval between the subsequent auto-retries.
+     * @return The interval between the subsequent retry in milliseconds.
      */
-    long getRetryInterval();
+    long getRetryInterval(HttpResponse response, HttpContext context);
 
 }

Modified: httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/client/DefaultServiceUnavailableRetryStrategy.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/client/DefaultServiceUnavailableRetryStrategy.java?rev=1687907&r1=1687906&r2=1687907&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/client/DefaultServiceUnavailableRetryStrategy.java (original)
+++ httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/client/DefaultServiceUnavailableRetryStrategy.java Sat Jun 27 10:50:12 2015
@@ -27,10 +27,15 @@
 
 package org.apache.http.impl.client;
 
+import java.util.Date;
+
+import org.apache.http.Header;
+import org.apache.http.HttpHeaders;
 import org.apache.http.HttpResponse;
 import org.apache.http.HttpStatus;
 import org.apache.http.annotation.Immutable;
 import org.apache.http.client.ServiceUnavailableRetryStrategy;
+import org.apache.http.client.utils.DateUtils;
 import org.apache.http.protocol.HttpContext;
 import org.apache.http.util.Args;
 
@@ -54,14 +59,14 @@ public class DefaultServiceUnavailableRe
      * Retry interval between subsequent requests, in milliseconds. Default
      * value is 1 second.
      */
-    private final long retryInterval;
+    private final long defaultRetryInterval;
 
-    public DefaultServiceUnavailableRetryStrategy(final int maxRetries, final int retryInterval) {
+    public DefaultServiceUnavailableRetryStrategy(final int maxRetries, final int defaultRetryInterval) {
         super();
         Args.positive(maxRetries, "Max retries");
-        Args.positive(retryInterval, "Retry interval");
+        Args.positive(defaultRetryInterval, "Retry interval");
         this.maxRetries = maxRetries;
-        this.retryInterval = retryInterval;
+        this.defaultRetryInterval = defaultRetryInterval;
     }
 
     public DefaultServiceUnavailableRetryStrategy() {
@@ -75,8 +80,21 @@ public class DefaultServiceUnavailableRe
     }
 
     @Override
-    public long getRetryInterval() {
-        return retryInterval;
+    public long getRetryInterval(final HttpResponse response, final HttpContext context) {
+        final Header header = response.getFirstHeader(HttpHeaders.RETRY_AFTER);
+        if (header != null) {
+            final String value = header.getValue();
+            try {
+                return Long.parseLong(value) * 1000;
+            } catch (NumberFormatException ignore) {
+                final Date date = DateUtils.parseDate(value);
+                if (date != null) {
+                    final long n = date.getTime() - System.currentTimeMillis();
+                    return n > 0 ? n : 0;
+                }
+            }
+        }
+        return this.defaultRetryInterval;
     }
 
 }

Modified: httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/execchain/ServiceUnavailableRetryExec.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/execchain/ServiceUnavailableRetryExec.java?rev=1687907&r1=1687906&r2=1687907&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/execchain/ServiceUnavailableRetryExec.java (original)
+++ httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/execchain/ServiceUnavailableRetryExec.java Sat Jun 27 10:50:12 2015
@@ -86,10 +86,12 @@ public class ServiceUnavailableRetryExec
             try {
                 if (this.retryStrategy.retryRequest(response, c, context)) {
                     response.close();
-                    final long nextInterval = this.retryStrategy.getRetryInterval();
+                    final long nextInterval = this.retryStrategy.getRetryInterval(response, context);
                     if (nextInterval > 0) {
                         try {
-                            this.log.trace("Wait for " + nextInterval);
+                            if (this.log.isDebugEnabled()) {
+                                this.log.debug("Wait for " + ((double) nextInterval / 1000) + " seconds" );
+                            }
                             Thread.sleep(nextInterval);
                         } catch (final InterruptedException e) {
                             Thread.currentThread().interrupt();

Added: httpcomponents/httpclient/trunk/httpclient/src/test/java/org/apache/http/impl/client/TestDefaultServiceUnavailableRetryStrategy.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient/src/test/java/org/apache/http/impl/client/TestDefaultServiceUnavailableRetryStrategy.java?rev=1687907&view=auto
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient/src/test/java/org/apache/http/impl/client/TestDefaultServiceUnavailableRetryStrategy.java (added)
+++ httpcomponents/httpclient/trunk/httpclient/src/test/java/org/apache/http/impl/client/TestDefaultServiceUnavailableRetryStrategy.java Sat Jun 27 10:50:12 2015
@@ -0,0 +1,99 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package org.apache.http.impl.client;
+
+import java.util.Date;
+
+import org.apache.http.HttpHeaders;
+import org.apache.http.HttpResponse;
+import org.apache.http.HttpVersion;
+import org.apache.http.client.utils.DateUtils;
+import org.apache.http.message.BasicHttpResponse;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TestDefaultServiceUnavailableRetryStrategy {
+
+    private DefaultServiceUnavailableRetryStrategy impl;
+
+    @Before
+    public void setup() {
+        this.impl = new DefaultServiceUnavailableRetryStrategy(3, 1234);
+    }
+
+    @Test
+    public void testBasics() throws Exception {
+        final HttpResponse response1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, 503, "Oppsie");
+        Assert.assertTrue(this.impl.retryRequest(response1, 1, null));
+        Assert.assertTrue(this.impl.retryRequest(response1, 2, null));
+        Assert.assertTrue(this.impl.retryRequest(response1, 3, null));
+        Assert.assertFalse(this.impl.retryRequest(response1, 4, null));
+        final HttpResponse response2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, 500, "Big Time Oppsie");
+        Assert.assertFalse(this.impl.retryRequest(response2, 1, null));
+
+        Assert.assertEquals(1234, this.impl.getRetryInterval(response1, null));
+    }
+
+    @Test
+    public void testRetryAfterHeaderAsLong() throws Exception {
+        final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 503, "Oppsie");
+        response.setHeader(HttpHeaders.RETRY_AFTER, "321");
+
+        Assert.assertEquals(321000, this.impl.getRetryInterval(response, null));
+    }
+
+    @Test
+    public void testRetryAfterHeaderAsDate() throws Exception {
+        this.impl = new DefaultServiceUnavailableRetryStrategy(3, 1);
+        final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 503, "Oppsie");
+
+        response.setHeader(HttpHeaders.RETRY_AFTER, DateUtils.formatDate(new Date(System.currentTimeMillis() + 100000L)));
+
+        Assert.assertTrue(this.impl.getRetryInterval(response, null) > 1);
+    }
+
+    @Test
+    public void testRetryAfterHeaderAsPastDate() throws Exception {
+        final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 503, "Oppsie");
+
+        response.setHeader(HttpHeaders.RETRY_AFTER, DateUtils.formatDate(new Date(System.currentTimeMillis() - 100000L)));
+
+        Assert.assertEquals(0, this.impl.getRetryInterval(response, null));
+    }
+
+    @Test
+    public void testInvalidRetryAfterHeader() throws Exception {
+        final DefaultServiceUnavailableRetryStrategy impl = new DefaultServiceUnavailableRetryStrategy(3, 1234);
+
+        final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 503, "Oppsie");
+        response.setHeader(HttpHeaders.RETRY_AFTER, "Stuff");
+
+        Assert.assertEquals(1234, impl.getRetryInterval(response, null));
+    }
+
+}

Propchange: httpcomponents/httpclient/trunk/httpclient/src/test/java/org/apache/http/impl/client/TestDefaultServiceUnavailableRetryStrategy.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpcomponents/httpclient/trunk/httpclient/src/test/java/org/apache/http/impl/client/TestDefaultServiceUnavailableRetryStrategy.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: httpcomponents/httpclient/trunk/httpclient/src/test/java/org/apache/http/impl/client/TestDefaultServiceUnavailableRetryStrategy.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: httpcomponents/httpclient/trunk/httpclient/src/test/java/org/apache/http/impl/execchain/TestServiceUnavailableRetryExec.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient/src/test/java/org/apache/http/impl/execchain/TestServiceUnavailableRetryExec.java?rev=1687907&r1=1687906&r2=1687907&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient/src/test/java/org/apache/http/impl/execchain/TestServiceUnavailableRetryExec.java (original)
+++ httpcomponents/httpclient/trunk/httpclient/src/test/java/org/apache/http/impl/execchain/TestServiceUnavailableRetryExec.java Sat Jun 27 10:50:12 2015
@@ -80,7 +80,9 @@ public class TestServiceUnavailableRetry
                 Mockito.<HttpResponse>any(),
                 Mockito.anyInt(),
                 Mockito.<HttpContext>any())).thenReturn(Boolean.TRUE, Boolean.FALSE);
-        Mockito.when(retryStrategy.getRetryInterval()).thenReturn(0L);
+        Mockito.when(retryStrategy.getRetryInterval(
+                Mockito.<HttpResponse>any(),
+                Mockito.<HttpContext>any())).thenReturn(0L);
 
         retryExec.execute(route, request, context, execAware);