View Javadoc
1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  package org.apache.hc.client5.http.impl;
28  
29  import java.io.IOException;
30  import java.net.ConnectException;
31  import java.net.NoRouteToHostException;
32  import java.net.SocketTimeoutException;
33  import java.net.UnknownHostException;
34  import java.util.Date;
35  
36  import javax.net.ssl.SSLException;
37  
38  import org.apache.hc.client5.http.classic.methods.HttpGet;
39  import org.apache.hc.client5.http.utils.DateUtils;
40  import org.apache.hc.core5.http.ConnectionClosedException;
41  import org.apache.hc.core5.http.HttpHeaders;
42  import org.apache.hc.core5.http.HttpResponse;
43  import org.apache.hc.core5.http.message.BasicHttpResponse;
44  import org.apache.hc.core5.util.TimeValue;
45  import org.junit.Assert;
46  import org.junit.Before;
47  import org.junit.Test;
48  
49  public class TestDefaultHttpRequestRetryStrategy {
50  
51      private DefaultHttpRequestRetryStrategy retryStrategy;
52  
53      @Before
54      public void setup() {
55          this.retryStrategy = new DefaultHttpRequestRetryStrategy(3, TimeValue.ofMilliseconds(1234L));
56      }
57  
58      @Test
59      public void testBasics() throws Exception {
60          final HttpResponse response1 = new BasicHttpResponse(503, "Oopsie");
61          Assert.assertTrue(this.retryStrategy.retryRequest(response1, 1, null));
62          Assert.assertTrue(this.retryStrategy.retryRequest(response1, 2, null));
63          Assert.assertTrue(this.retryStrategy.retryRequest(response1, 3, null));
64          Assert.assertFalse(this.retryStrategy.retryRequest(response1, 4, null));
65          final HttpResponse response2 = new BasicHttpResponse(500, "Big Time Oopsie");
66          Assert.assertFalse(this.retryStrategy.retryRequest(response2, 1, null));
67          final HttpResponse response3 = new BasicHttpResponse(429, "Oopsie");
68          Assert.assertTrue(this.retryStrategy.retryRequest(response3, 1, null));
69          Assert.assertTrue(this.retryStrategy.retryRequest(response3, 2, null));
70          Assert.assertTrue(this.retryStrategy.retryRequest(response3, 3, null));
71          Assert.assertFalse(this.retryStrategy.retryRequest(response3, 4, null));
72  
73          Assert.assertEquals(TimeValue.ofMilliseconds(1234L), this.retryStrategy.getRetryInterval(response1, 1, null));
74      }
75  
76      @Test
77      public void testRetryAfterHeaderAsLong() throws Exception {
78          final HttpResponse response = new BasicHttpResponse(503, "Oopsie");
79          response.setHeader(HttpHeaders.RETRY_AFTER, "321");
80  
81          Assert.assertEquals(TimeValue.ofSeconds(321L), this.retryStrategy.getRetryInterval(response, 3, null));
82      }
83  
84      @Test
85      public void testRetryAfterHeaderAsDate() throws Exception {
86          this.retryStrategy = new DefaultHttpRequestRetryStrategy(3, TimeValue.ZERO_MILLISECONDS);
87          final HttpResponse response = new BasicHttpResponse(503, "Oopsie");
88          response.setHeader(HttpHeaders.RETRY_AFTER, DateUtils.formatDate(new Date(System.currentTimeMillis() + 100000L)));
89  
90          Assert.assertTrue(this.retryStrategy.getRetryInterval(response, 3, null).compareTo(TimeValue.ZERO_MILLISECONDS) > 0);
91      }
92  
93      @Test
94      public void testRetryAfterHeaderAsPastDate() throws Exception {
95          final HttpResponse response = new BasicHttpResponse(503, "Oopsie");
96          response.setHeader(HttpHeaders.RETRY_AFTER, DateUtils.formatDate(new Date(System.currentTimeMillis() - 100000L)));
97  
98          Assert.assertEquals(TimeValue.ofMilliseconds(1234L), this.retryStrategy.getRetryInterval(response, 3, null));
99      }
100 
101     @Test
102     public void testInvalidRetryAfterHeader() throws Exception {
103         final HttpResponse response = new BasicHttpResponse(503, "Oopsie");
104         response.setHeader(HttpHeaders.RETRY_AFTER, "Stuff");
105 
106         Assert.assertEquals(TimeValue.ofMilliseconds(1234L), retryStrategy.getRetryInterval(response, 3, null));
107     }
108 
109     @Test
110     public void noRetryOnConnectTimeout() throws Exception {
111         final HttpGet request = new HttpGet("/");
112 
113         Assert.assertFalse(retryStrategy.retryRequest(request, new SocketTimeoutException(), 1, null));
114     }
115 
116     @Test
117     public void noRetryOnConnect() throws Exception {
118         final HttpGet request = new HttpGet("/");
119 
120         Assert.assertFalse(retryStrategy.retryRequest(request, new ConnectException(), 1, null));
121     }
122 
123     @Test
124     public void noRetryOnConnectionClosed() throws Exception {
125         final HttpGet request = new HttpGet("/");
126 
127         Assert.assertFalse(retryStrategy.retryRequest(request, new ConnectionClosedException(), 1, null));
128     }
129 
130     @Test
131     public void noRetryForNoRouteToHostException() {
132         final HttpGet request = new HttpGet("/");
133 
134         Assert.assertFalse(retryStrategy.retryRequest(request, new NoRouteToHostException(), 1, null));
135     }
136 
137     @Test
138     public void noRetryOnSSLFailure() throws Exception {
139         final HttpGet request = new HttpGet("/");
140 
141         Assert.assertFalse(retryStrategy.retryRequest(request, new SSLException("encryption failed"), 1, null));
142     }
143 
144     @Test
145     public void noRetryOnUnknownHost() throws Exception {
146         final HttpGet request = new HttpGet("/");
147 
148         Assert.assertFalse(retryStrategy.retryRequest(request, new UnknownHostException(), 1, null));
149     }
150 
151     @Test
152     public void noRetryOnAbortedRequests() throws Exception {
153         final HttpGet request = new HttpGet("/");
154         request.cancel();
155 
156         Assert.assertFalse(retryStrategy.retryRequest(request, new IOException(), 1, null));
157     }
158 
159     @Test
160     public void retryOnNonAbortedRequests() throws Exception {
161         final HttpGet request = new HttpGet("/");
162 
163         Assert.assertTrue(retryStrategy.retryRequest(request, new IOException(), 1, null));
164     }
165 
166 }