diff options
author | Thomas <> | 2024-04-03 18:40:59 +0200 |
---|---|---|
committer | Thomas <> | 2024-04-03 18:40:59 +0200 |
commit | ff340b3aec5193b066b3cf6ee6cbc9c542de48df (patch) | |
tree | 00186bd13aa86f6016383aa96837f1a2de76a239 | |
parent | 487011328411309e0be774d5e9371346a788d9ba (diff) | |
download | EAAF-Components-ff340b3aec5193b066b3cf6ee6cbc9c542de48df.tar.gz EAAF-Components-ff340b3aec5193b066b3cf6ee6cbc9c542de48df.tar.bz2 EAAF-Components-ff340b3aec5193b066b3cf6ee6cbc9c542de48df.zip |
fix(http): include retry on HTTP POST requests
Reason: that feature looks be removed during refactoring from Apache HTTP Client v4.x to 5.x
4 files changed, 108 insertions, 33 deletions
diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/http/EaafHttpRequestRetryHandler.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/http/EaafHttpRequestRetryHandler.java index 026b76c4..6ea13905 100644 --- a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/http/EaafHttpRequestRetryHandler.java +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/http/EaafHttpRequestRetryHandler.java @@ -7,11 +7,15 @@ import javax.net.ssl.SSLException; import org.apache.hc.client5.http.HttpRequestRetryStrategy; import org.apache.hc.client5.http.impl.DefaultHttpRequestRetryStrategy; +import org.apache.hc.core5.http.HttpRequest; +import org.apache.hc.core5.http.Method; import org.apache.hc.core5.util.TimeValue; public class EaafHttpRequestRetryHandler extends DefaultHttpRequestRetryStrategy implements HttpRequestRetryStrategy { + private boolean allowHttpPostRetry; + /** * Create the request retry handler using the following list of non-retriable. * IOException classes: <br> @@ -25,15 +29,48 @@ public class EaafHttpRequestRetryHandler extends DefaultHttpRequestRetryStrategy * <li>502</li> * </ul> * After two seconds if no {@code Retry-After} header was set. + * <p> + * Do not allow retry of HTTP POST + * </p> * * @param retryCount how many times to retry; 0 means no retries */ public EaafHttpRequestRetryHandler(final int retryCount) { + this(retryCount, false); + + } + + /** + * Create the request retry handler using the following list of non-retriable. + * IOException classes: <br> + * <ul> + * <li>UnknownHostException</li> + * <li>SSLException</li> + * </ul> + * HTTP StatusCodes: + * <ul> + * <li>429</li> + * <li>502</li> + * </ul> + * After two seconds if no {@code Retry-After} header was set. + * + * @param retryCount how many times to retry; 0 means no retries + * @param retryHttpPost In case of <code>true</code> allow retry of HTTP POST + * too + */ + public EaafHttpRequestRetryHandler(final int retryCount, final boolean retryHttpPost) { super(retryCount, TimeValue.ofSeconds(2), Arrays.asList( UnknownHostException.class, SSLException.class), Arrays.asList(429, 502)); + allowHttpPostRetry = retryHttpPost; + + } + + protected boolean handleAsIdempotent(final HttpRequest request) { + return allowHttpPostRetry && Method.POST.isSame(request.getMethod()) + || Method.isIdempotent(request.getMethod()); } diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/http/HttpClientConfiguration.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/http/HttpClientConfiguration.java index 2081bd24..f978fa4c 100644 --- a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/http/HttpClientConfiguration.java +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/http/HttpClientConfiguration.java @@ -67,6 +67,9 @@ public class HttpClientConfiguration { private boolean followHttpRedirects = true; @Setter + private boolean httpPostRetryAllowed = false; + + @Setter private int httpErrorRetryCount = 3; @Setter diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/http/HttpClientFactory.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/http/HttpClientFactory.java index 62e781b9..7a71bfab 100644 --- a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/http/HttpClientFactory.java +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/http/HttpClientFactory.java @@ -81,6 +81,8 @@ public class HttpClientFactory implements IHttpClientFactory { "client.http.connection.timeout.request"; public static final String PROP_CONFIG_CLIENT_HTTP_CONNECTION_RETRY_COUNT = "client.http.connection.retry.count"; + public static final String PROP_CONFIG_CLIENT_HTTP_CONNECTION_RETRY_POST = + "client.http.connection.retry.post"; public static final String PROP_CONFIG_CLIENT_HTTP_SSL_HOSTNAMEVERIFIER_TRUSTALL = "client.http.ssl.hostnameverifier.trustall"; @@ -210,7 +212,8 @@ public class HttpClientFactory implements IHttpClientFactory { log.info("Set HTTP error-retry to {} for http-client: {}", config.getHttpErrorRetryCount(), config.getFriendlyName()); builder.setRetryStrategy(new EaafHttpRequestRetryHandler( - config.getHttpErrorRetryCount())); + config.getHttpErrorRetryCount(), + config.isHttpPostRetryAllowed())); } else { log.info("Disable HTTP error-retry for http-client: {}", config.getFriendlyName()); @@ -309,6 +312,8 @@ public class HttpClientFactory implements IHttpClientFactory { config.setHttpErrorRetryCount(Integer.parseInt(basicConfig.getBasicConfiguration( PROP_CONFIG_CLIENT_HTTP_CONNECTION_RETRY_COUNT, DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_RETRY_COUNT))); + config.setHttpPostRetryAllowed(basicConfig.getBasicConfigurationBoolean( + PROP_CONFIG_CLIENT_HTTP_CONNECTION_RETRY_POST, false)); config.setEnableHttpProxyMode(basicConfig.getBasicConfigurationBoolean( PROP_CONFIG_CLIENT_HTTP_PROXY_ENABLED, false)); diff --git a/eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/test/http/HttpClientFactoryTest.java b/eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/test/http/HttpClientFactoryTest.java index 243205c9..c566380e 100644 --- a/eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/test/http/HttpClientFactoryTest.java +++ b/eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/test/http/HttpClientFactoryTest.java @@ -394,38 +394,6 @@ public class HttpClientFactoryTest { } @Test - public void httpPostRetryNotAllowed() throws EaafException, InterruptedException, - ClientProtocolException, IOException { - final HttpClientConfiguration config = - new HttpClientConfiguration("jUnit_retry_" + RandomStringUtils.randomAlphabetic(3)); - config.setHttpErrorRetryCount(2); - - final CloseableHttpClient client = httpClientFactory.getHttpClient(config); - Assert.assertNotNull("No httpClient", client); - - - mockWebServer = new MockWebServer(); - mockServerUrl = mockWebServer.url("/sp/junit"); - mockWebServer.enqueue(new MockResponse() - .setSocketPolicy(SocketPolicy.NO_RESPONSE) - .setResponseCode(HttpURLConnection.HTTP_NO_CONTENT)); - mockWebServer.enqueue(new MockResponse().setResponseCode(200) - .setBody("GetData")); - - //request webservice - final HttpUriRequest httpGet1 = new HttpPost(mockServerUrl.url().toString()); - try { - client.execute(httpGet1); - Assert.fail("HTTP POST retry not allowed"); - - } catch (final SocketTimeoutException e) { - Assert.assertNotNull("No errorMsg", e.getMessage()); - - } - - } - - @Test public void testHttpClientRetryOneTime() throws EaafException, InterruptedException, ClientProtocolException, IOException { final HttpClientConfiguration config = @@ -552,6 +520,68 @@ public class HttpClientFactoryTest { } @Test + public void testHttpClientRetryOneTimePost() throws EaafException, InterruptedException, + ClientProtocolException, IOException { + final HttpClientConfiguration config = + new HttpClientConfiguration("jUnit_retry_" + RandomStringUtils.randomAlphabetic(3)); + config.setHttpErrorRetryCount(2); + config.setHttpPostRetryAllowed(true); + + final CloseableHttpClient client = httpClientFactory.getHttpClient(config); + Assert.assertNotNull("No httpClient", client); + + mockWebServer = new MockWebServer(); + mockServerUrl = mockWebServer.url("/sp/junit"); + mockWebServer.enqueue(new MockResponse() + .setSocketPolicy(SocketPolicy.NO_RESPONSE) + .setResponseCode(HttpURLConnection.HTTP_NO_CONTENT)); + + String bodyData = RandomStringUtils.randomAlphanumeric(10); + mockWebServer.enqueue(new MockResponse().setResponseCode(200) + .setBody(bodyData)); + + // request webservice + final HttpUriRequest httpGet1 = new HttpPost(mockServerUrl.url().toString()); + final Triple<StatusLine, ByteArrayInputStream, ContentType> httpResp1 = client.execute(httpGet1, + HttpUtils.bodyStatusCodeResponseHandler()); + Assert.assertEquals("http statusCode", 200, httpResp1.getFirst().getStatusCode()); + Assert.assertEquals("http statusCode", bodyData, new String(StreamUtils.readStream(httpResp1 + .getSecond()))); + + } + + @Test + public void httpPostRetryNotAllowed() throws EaafException, InterruptedException, + ClientProtocolException, IOException { + final HttpClientConfiguration config = + new HttpClientConfiguration("jUnit_retry_" + RandomStringUtils.randomAlphabetic(3)); + config.setHttpErrorRetryCount(2); + config.setHttpPostRetryAllowed(false); + + final CloseableHttpClient client = httpClientFactory.getHttpClient(config); + Assert.assertNotNull("No httpClient", client); + + mockWebServer = new MockWebServer(); + mockServerUrl = mockWebServer.url("/sp/junit"); + mockWebServer.enqueue(new MockResponse() + .setSocketPolicy(SocketPolicy.NO_RESPONSE) + .setResponseCode(HttpURLConnection.HTTP_NO_CONTENT)); + mockWebServer.enqueue(new MockResponse().setResponseCode(200) + .setBody("GetData")); + + // request webservices + final HttpUriRequest httpGet1 = new HttpPost(mockServerUrl.url().toString()); + try { + client.execute(httpGet1); + Assert.fail("HTTP POST retry not allowed"); + + } catch (final SocketTimeoutException e) { + Assert.assertNotNull("No errorMsg", e.getMessage()); + + } + } + + @Test public void getCustomClientBasicAuthNoPassword() throws EaafException { final HttpClientConfiguration config = new HttpClientConfiguration("jUnit"); config.setAuthMode("password"); |