You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by en...@apache.org on 2020/09/22 17:32:19 UTC

[sling-org-apache-sling-testing-clients] branch master updated: SLING-9757 Add configurable connection timeout for SlingClient

This is an automated email from the ASF dual-hosted git repository.

enorman pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-testing-clients.git


The following commit(s) were added to refs/heads/master by this push:
     new 7eecfdc  SLING-9757 Add configurable connection timeout for SlingClient
7eecfdc is described below

commit 7eecfdc4def55da25f77d3937bbff483e59a769b
Author: Eric Norman <en...@apache.org>
AuthorDate: Tue Sep 22 10:32:09 2020 -0700

    SLING-9757 Add configurable connection timeout for SlingClient
---
 .../apache/sling/testing/clients/SlingClient.java  |  38 ++++--
 .../clients/SlingClientConnectionTimeoutTest.java  | 134 +++++++++++++++++++++
 2 files changed, 162 insertions(+), 10 deletions(-)

diff --git a/src/main/java/org/apache/sling/testing/clients/SlingClient.java b/src/main/java/org/apache/sling/testing/clients/SlingClient.java
index 58c4ef3..7a64ddd 100644
--- a/src/main/java/org/apache/sling/testing/clients/SlingClient.java
+++ b/src/main/java/org/apache/sling/testing/clients/SlingClient.java
@@ -16,6 +16,16 @@
  */
 package org.apache.sling.testing.clients;
 
+import static org.apache.http.HttpStatus.SC_CREATED;
+import static org.apache.http.HttpStatus.SC_OK;
+
+import java.io.File;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
 import org.apache.commons.lang3.StringUtils;
 import org.apache.http.HttpEntity;
 import org.apache.http.HttpRequestInterceptor;
@@ -25,6 +35,7 @@ import org.apache.http.annotation.Immutable;
 import org.apache.http.client.CookieStore;
 import org.apache.http.client.CredentialsProvider;
 import org.apache.http.client.RedirectStrategy;
+import org.apache.http.client.config.RequestConfig;
 import org.apache.http.client.entity.UrlEncodedFormEntity;
 import org.apache.http.entity.ContentType;
 import org.apache.http.entity.mime.MultipartEntityBuilder;
@@ -32,20 +43,15 @@ import org.apache.http.impl.client.CloseableHttpClient;
 import org.apache.http.impl.client.HttpClientBuilder;
 import org.apache.sling.testing.clients.interceptors.DelayRequestInterceptor;
 import org.apache.sling.testing.clients.interceptors.TestDescriptionInterceptor;
-import org.apache.sling.testing.clients.util.*;
+import org.apache.sling.testing.clients.util.FormEntityBuilder;
+import org.apache.sling.testing.clients.util.HttpUtils;
+import org.apache.sling.testing.clients.util.JsonUtils;
+import org.apache.sling.testing.clients.util.ServerErrorRetryStrategy;
 import org.apache.sling.testing.clients.util.poller.AbstractPoller;
 import org.apache.sling.testing.clients.util.poller.Polling;
+import org.apache.sling.testing.timeouts.TimeoutsProvider;
 import org.codehaus.jackson.JsonNode;
 
-import java.io.File;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.TimeoutException;
-
-import static org.apache.http.HttpStatus.SC_CREATED;
-import static org.apache.http.HttpStatus.SC_OK;
-
 /**
  * <p>The Base class for all Integration Test Clients. It provides generic methods to send HTTP requests to a server. </p>
  *
@@ -56,6 +62,7 @@ import static org.apache.http.HttpStatus.SC_OK;
 public class SlingClient extends AbstractSlingClient {
 
     public static final String DEFAULT_NODE_TYPE = "sling:OrderedFolder";
+    public static final String CLIENT_CONNECTION_TIMEOUT_PROP = "sling.client.connection.timeout.seconds";
 
     /**
      * Constructor used by Builders and adaptTo(). <b>Should never be called directly from the code.</b>
@@ -692,6 +699,17 @@ public class SlingClient extends AbstractSlingClient {
             // HTTP request strategy
             httpClientBuilder.setServiceUnavailableRetryStrategy(new ServerErrorRetryStrategy());
 
+            // connection timeouts
+            int timeoutSeconds = TimeoutsProvider.getInstance().getTimeout(CLIENT_CONNECTION_TIMEOUT_PROP, -1);
+            if (timeoutSeconds > 0) {
+                int timeoutMs = (int)TimeUnit.SECONDS.toMillis(timeoutSeconds);
+				RequestConfig config = RequestConfig.custom()
+                        .setConnectTimeout(timeoutMs)
+                        .setConnectionRequestTimeout(timeoutMs)
+                        .setSocketTimeout(timeoutMs).build();
+                this.httpClientBuilder.setDefaultRequestConfig(config);
+            }
+
             return this;
         }
 
diff --git a/src/test/java/org/apache/sling/testing/clients/SlingClientConnectionTimeoutTest.java b/src/test/java/org/apache/sling/testing/clients/SlingClientConnectionTimeoutTest.java
new file mode 100644
index 0000000..58e4570
--- /dev/null
+++ b/src/test/java/org/apache/sling/testing/clients/SlingClientConnectionTimeoutTest.java
@@ -0,0 +1,134 @@
+/*
+ * 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.
+ */
+package org.apache.sling.testing.clients;
+
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+import java.net.SocketTimeoutException;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import org.apache.http.HttpException;
+import org.apache.http.HttpRequest;
+import org.apache.http.HttpResponse;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.protocol.HttpContext;
+import org.apache.http.protocol.HttpRequestHandler;
+import org.junit.ClassRule;
+import org.junit.Test;
+
+/**
+ * SLING-9757 verify configurable connection timeout for SlingClient
+ */
+public class SlingClientConnectionTimeoutTest {
+	private static final String GET_TIMEOUT_PATH = "/test/timeout/resource";
+	private static final String OK_RESPONSE = "TEST_OK";
+
+	@ClassRule
+	public static HttpServerRule httpServer = new HttpServerRule() {
+		@Override
+		protected void registerHandlers() throws IOException {
+			serverBootstrap.registerHandler(GET_TIMEOUT_PATH, new HttpRequestHandler() {
+				@Override
+				public void handle(HttpRequest request, HttpResponse response, HttpContext context) throws HttpException, IOException {
+					// block for 15 seconds
+					try {
+						Thread.sleep(TimeUnit.SECONDS.toMillis(15));
+					} catch (InterruptedException e) {
+						// ignore
+					}
+					response.setEntity(new StringEntity(OK_RESPONSE));
+				}
+			});
+		}
+	};
+
+	/**
+	 * Test that a configured connection timeout will kill the client request when it
+	 * does not respond quickly enough
+	 */
+	@Test
+	public void testConnectionTimeout() throws Exception {
+		String originalValue = System.getProperty(SlingClient.CLIENT_CONNECTION_TIMEOUT_PROP, null);
+		try {
+			// timeout when the request takes more than 2 second
+			System.setProperty(SlingClient.CLIENT_CONNECTION_TIMEOUT_PROP, "2");
+			try (SlingClient c = new SlingClient(httpServer.getURI(), "user", "pass")) {
+				// start the client request
+				c.doGet(GET_TIMEOUT_PATH);
+				
+				// should not get here
+				fail("Did not recieve the expected SocketTimeoutException");
+			}
+		} catch (Exception e) {
+			Throwable cause = e.getCause();
+			assertTrue("expected a SocketTimeoutException", cause instanceof SocketTimeoutException);
+		} finally {
+			//put the original value back
+			if (originalValue == null) {
+				System.clearProperty(SlingClient.CLIENT_CONNECTION_TIMEOUT_PROP);
+			} else {
+				System.setProperty(SlingClient.CLIENT_CONNECTION_TIMEOUT_PROP, originalValue);
+			}
+		}    	
+	}
+	
+	/**
+	 * Test that when no connection timeout is supplied, the client connection waits
+	 */
+	@Test
+	public void testConnectionNoTimeout() throws Exception {
+		String originalValue = System.getProperty(SlingClient.CLIENT_CONNECTION_TIMEOUT_PROP, null);
+		try {
+			// clear out any timeout configuration
+			System.clearProperty(SlingClient.CLIENT_CONNECTION_TIMEOUT_PROP);
+
+			try (SlingClient c = new SlingClient(httpServer.getURI(), "user", "pass")) {
+				SlingHttpResponse response = null;
+				CompletableFuture<SlingHttpResponse> endpointCall = CompletableFuture.supplyAsync(() -> {
+					try {
+						return c.doGet(GET_TIMEOUT_PATH);
+					} catch (ClientException e1) {
+						// TODO Auto-generated catch block
+						e1.printStackTrace();
+					}
+					return null;
+				});
+
+				try {
+					response = endpointCall.get(2, TimeUnit.SECONDS);
+					assertNull("Did not expect a response from the endpoint", response);
+				} catch (TimeoutException e) {
+					// expected that we killed the future when it didn't finish
+					//  on it's own in a timely manner
+				}    		
+			}
+		} finally {
+			//put the original value back
+			if (originalValue == null) {
+				System.clearProperty(SlingClient.CLIENT_CONNECTION_TIMEOUT_PROP);
+			} else {
+				System.setProperty(SlingClient.CLIENT_CONNECTION_TIMEOUT_PROP, originalValue);
+			}
+		}    	
+	}
+
+}