1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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.time.Instant;
35 import java.time.temporal.ChronoUnit;
36
37 import javax.net.ssl.SSLException;
38
39 import org.apache.hc.client5.http.classic.methods.HttpGet;
40 import org.apache.hc.client5.http.utils.DateUtils;
41 import org.apache.hc.core5.http.ConnectionClosedException;
42 import org.apache.hc.core5.http.HttpHeaders;
43 import org.apache.hc.core5.http.HttpResponse;
44 import org.apache.hc.core5.http.message.BasicHttpResponse;
45 import org.apache.hc.core5.util.TimeValue;
46 import org.junit.jupiter.api.Assertions;
47 import org.junit.jupiter.api.BeforeEach;
48 import org.junit.jupiter.api.Test;
49
50 class TestDefaultHttpRequestRetryStrategy {
51
52 private DefaultHttpRequestRetryStrategy retryStrategy;
53
54 @BeforeEach
55 void setup() {
56 this.retryStrategy = new DefaultHttpRequestRetryStrategy(3, TimeValue.ofMilliseconds(1234L));
57 }
58
59 @Test
60 void testBasics() {
61 final HttpResponse response1 = new BasicHttpResponse(503, "Oopsie");
62 Assertions.assertTrue(this.retryStrategy.retryRequest(response1, 1, null));
63 Assertions.assertTrue(this.retryStrategy.retryRequest(response1, 2, null));
64 Assertions.assertTrue(this.retryStrategy.retryRequest(response1, 3, null));
65 Assertions.assertFalse(this.retryStrategy.retryRequest(response1, 4, null));
66 final HttpResponse response2 = new BasicHttpResponse(500, "Big Time Oopsie");
67 Assertions.assertFalse(this.retryStrategy.retryRequest(response2, 1, null));
68 final HttpResponse response3 = new BasicHttpResponse(429, "Oopsie");
69 Assertions.assertTrue(this.retryStrategy.retryRequest(response3, 1, null));
70 Assertions.assertTrue(this.retryStrategy.retryRequest(response3, 2, null));
71 Assertions.assertTrue(this.retryStrategy.retryRequest(response3, 3, null));
72 Assertions.assertFalse(this.retryStrategy.retryRequest(response3, 4, null));
73
74 Assertions.assertEquals(TimeValue.ofMilliseconds(1234L), this.retryStrategy.getRetryInterval(response1, 1, null));
75 }
76
77 @Test
78 void testRetryAfterHeaderAsLong() {
79 final HttpResponse response = new BasicHttpResponse(503, "Oopsie");
80 response.setHeader(HttpHeaders.RETRY_AFTER, "321");
81
82 Assertions.assertEquals(TimeValue.ofSeconds(321L), this.retryStrategy.getRetryInterval(response, 3, null));
83 }
84
85 @Test
86 void testRetryAfterHeaderAsDate() {
87 this.retryStrategy = new DefaultHttpRequestRetryStrategy(3, TimeValue.ZERO_MILLISECONDS);
88 final HttpResponse response = new BasicHttpResponse(503, "Oopsie");
89 response.setHeader(HttpHeaders.RETRY_AFTER, DateUtils.formatStandardDate(Instant.now().plus(100, ChronoUnit.SECONDS)));
90
91 Assertions.assertTrue(this.retryStrategy.getRetryInterval(response, 3, null).compareTo(TimeValue.ZERO_MILLISECONDS) > 0);
92 }
93
94 @Test
95 void testRetryAfterHeaderAsPastDate() {
96 final HttpResponse response = new BasicHttpResponse(503, "Oopsie");
97 response.setHeader(HttpHeaders.RETRY_AFTER, DateUtils.formatStandardDate(Instant.now().minus(100, ChronoUnit.SECONDS)));
98
99 Assertions.assertEquals(TimeValue.ofMilliseconds(1234L), this.retryStrategy.getRetryInterval(response, 3, null));
100 }
101
102 @Test
103 void testInvalidRetryAfterHeader() {
104 final HttpResponse response = new BasicHttpResponse(503, "Oopsie");
105 response.setHeader(HttpHeaders.RETRY_AFTER, "Stuff");
106
107 Assertions.assertEquals(TimeValue.ofMilliseconds(1234L), retryStrategy.getRetryInterval(response, 3, null));
108 }
109
110 @Test
111 void noRetryOnConnectTimeout() {
112 final HttpGet request = new HttpGet("/");
113
114 Assertions.assertFalse(retryStrategy.retryRequest(request, new SocketTimeoutException(), 1, null));
115 }
116
117 @Test
118 void noRetryOnConnect() {
119 final HttpGet request = new HttpGet("/");
120
121 Assertions.assertFalse(retryStrategy.retryRequest(request, new ConnectException(), 1, null));
122 }
123
124 @Test
125 void noRetryOnConnectionClosed() {
126 final HttpGet request = new HttpGet("/");
127
128 Assertions.assertFalse(retryStrategy.retryRequest(request, new ConnectionClosedException(), 1, null));
129 }
130
131 @Test
132 void noRetryForNoRouteToHostException() {
133 final HttpGet request = new HttpGet("/");
134
135 Assertions.assertFalse(retryStrategy.retryRequest(request, new NoRouteToHostException(), 1, null));
136 }
137
138 @Test
139 void noRetryOnSSLFailure() {
140 final HttpGet request = new HttpGet("/");
141
142 Assertions.assertFalse(retryStrategy.retryRequest(request, new SSLException("encryption failed"), 1, null));
143 }
144
145 @Test
146 void noRetryOnUnknownHost() {
147 final HttpGet request = new HttpGet("/");
148
149 Assertions.assertFalse(retryStrategy.retryRequest(request, new UnknownHostException(), 1, null));
150 }
151
152 @Test
153 void noRetryOnAbortedRequests() {
154 final HttpGet request = new HttpGet("/");
155 request.cancel();
156
157 Assertions.assertFalse(retryStrategy.retryRequest(request, new IOException(), 1, null));
158 }
159
160 @Test
161 void retryOnNonAbortedRequests() {
162 final HttpGet request = new HttpGet("/");
163
164 Assertions.assertTrue(retryStrategy.retryRequest(request, new IOException(), 1, null));
165 }
166
167 }