You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ro...@apache.org on 2019/06/12 14:51:46 UTC

[sling-whiteboard] branch feature/http-timeout-okhttp created (now 55d6fab)

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

rombert pushed a change to branch feature/http-timeout-okhttp
in repository https://gitbox.apache.org/repos/asf/sling-whiteboard.git.


      at 55d6fab  Added support for okhttp

This branch includes the following new commits:

     new 55d6fab  Added support for okhttp

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[sling-whiteboard] 01/01: Added support for okhttp

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to branch feature/http-timeout-okhttp
in repository https://gitbox.apache.org/repos/asf/sling-whiteboard.git

commit 55d6fabcbb6b2602f067ece5ef2846218ee6eefd
Author: Robert Munteanu <ro...@apache.org>
AuthorDate: Wed Jun 12 16:51:20 2019 +0200

    Added support for okhttp
---
 url-connection-agent/pom.xml                       |  6 ++
 .../main/java/org/apache/sling/uca/impl/Agent.java |  3 +-
 .../sling/uca/impl/OkHttpTimeoutTransformer.java   | 75 ++++++++++++++++++++++
 .../java/org/apache/sling/uca/impl/AgentIT.java    | 11 +++-
 .../apache/sling/uca/impl/HttpClientLauncher.java  | 21 +++++-
 5 files changed, 112 insertions(+), 4 deletions(-)

diff --git a/url-connection-agent/pom.xml b/url-connection-agent/pom.xml
index c148a64..d37503b 100644
--- a/url-connection-agent/pom.xml
+++ b/url-connection-agent/pom.xml
@@ -133,5 +133,11 @@
             <version>4.5.4</version>
             <scope>test</scope>
         </dependency>
+        <dependency>
+          <groupId>com.squareup.okhttp3</groupId>
+          <artifactId>okhttp</artifactId>
+          <version>3.14.2</version>
+          <scope>test</scope>
+        </dependency>
     </dependencies>
 </project>
\ No newline at end of file
diff --git a/url-connection-agent/src/main/java/org/apache/sling/uca/impl/Agent.java b/url-connection-agent/src/main/java/org/apache/sling/uca/impl/Agent.java
index e523155..3842268 100644
--- a/url-connection-agent/src/main/java/org/apache/sling/uca/impl/Agent.java
+++ b/url-connection-agent/src/main/java/org/apache/sling/uca/impl/Agent.java
@@ -42,7 +42,8 @@ public class Agent {
         ClassFileTransformer[] transformers = new ClassFileTransformer[] {
             new JavaNetTimeoutTransformer(connectTimeout, readTimeout),
             new HttpClient3TimeoutTransformer(connectTimeout, readTimeout),
-            new HttpClient4TimeoutTransformer(connectTimeout, readTimeout)
+            new HttpClient4TimeoutTransformer(connectTimeout, readTimeout),
+            new OkHttpTimeoutTransformer(connectTimeout, readTimeout)
         };
         
         for ( ClassFileTransformer transformer : transformers )
diff --git a/url-connection-agent/src/main/java/org/apache/sling/uca/impl/OkHttpTimeoutTransformer.java b/url-connection-agent/src/main/java/org/apache/sling/uca/impl/OkHttpTimeoutTransformer.java
new file mode 100644
index 0000000..a93e223
--- /dev/null
+++ b/url-connection-agent/src/main/java/org/apache/sling/uca/impl/OkHttpTimeoutTransformer.java
@@ -0,0 +1,75 @@
+/*
+ * 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.uca.impl;
+
+import java.lang.instrument.ClassFileTransformer;
+import java.lang.instrument.IllegalClassFormatException;
+import java.security.ProtectionDomain;
+
+import javassist.ClassPool;
+import javassist.CtClass;
+import javassist.CtConstructor;
+import javassist.CtField;
+import javassist.bytecode.Descriptor;
+
+/**
+ * Sets timeouts for HTTP calls done using <em>OkHttp 3.x</em>
+ * 
+ * <p>It inserts two calls to <tt>okhttp3.OkHttpClient$Builder</tt> that set default
+ * values for <tt>connectTimeout</tt> and <tt>readTimeout</tt>.</p>
+ */
+public class OkHttpTimeoutTransformer implements ClassFileTransformer {
+
+    private static final String REQUEST_CONFIG_BUILDER_CLASS_NAME = Descriptor.toJvmName("okhttp3.OkHttpClient$Builder");
+    
+    private final long connectTimeoutMillis;
+    private final long readTimeoutMillis;
+    
+    public OkHttpTimeoutTransformer(long connectTimeoutMillis, long readTimeoutMillis) {
+        this.connectTimeoutMillis = connectTimeoutMillis;
+        this.readTimeoutMillis = readTimeoutMillis;
+    }
+
+    @Override
+    public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
+            ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
+        try {
+            if ( REQUEST_CONFIG_BUILDER_CLASS_NAME.equals(className) ) {
+                Log.get().log("%s asked to transform %s", getClass().getSimpleName(), className);
+                
+                ClassPool defaultPool = ClassPool.getDefault();
+                CtClass cc = defaultPool.get(Descriptor.toJavaName(className));
+                
+                // TODO - access the default constructor explicitly in case it changes
+                CtConstructor noArgCtor =  cc.getConstructors()[0];
+                CtField connectTimeout = cc.getDeclaredField("connectTimeout");
+                CtField readTimeout = cc.getDeclaredField("readTimeout");
+                noArgCtor.insertAfter("this." + connectTimeout.getName() + " = " + connectTimeoutMillis + ";");
+                noArgCtor.insertAfter("this." + readTimeout.getName() + " = " + readTimeoutMillis + ";");
+                
+                classfileBuffer = cc.toBytecode();
+                cc.detach();
+                Log.get().log("Transformation complete.");
+            }
+            return classfileBuffer;
+        } catch (Exception e) {
+            Log.get().fatal("Transformation failed", e);
+            return null;
+        }
+    }
+
+}
diff --git a/url-connection-agent/src/test/java/org/apache/sling/uca/impl/AgentIT.java b/url-connection-agent/src/test/java/org/apache/sling/uca/impl/AgentIT.java
index e8b6ac8..8ea2b52 100644
--- a/url-connection-agent/src/test/java/org/apache/sling/uca/impl/AgentIT.java
+++ b/url-connection-agent/src/test/java/org/apache/sling/uca/impl/AgentIT.java
@@ -93,6 +93,11 @@ public class AgentIT {
                 expectedClass = org.apache.http.conn.ConnectTimeoutException.class;
                 expectedMessageRegex = "Connect to repo1.maven.org:81 \\[.*\\] failed: connect timed out";
                 break;
+            case OkHttp:
+                expectedClass = SocketTimeoutException.class;
+                expectedMessageRegex = "connect timed out";
+                break;
+                
             default:
                 throw new AssertionError("Unhandled clientType " + clientType);
         }
@@ -113,7 +118,7 @@ public class AgentIT {
         
         RecordedThrowable error = assertTimeout(ofSeconds(5),  () -> runTest("http://localhost:" + server.getLocalPort(), clientType));
         assertEquals(SocketTimeoutException.class.getName(), error.className);
-        assertEquals("Read timed out", error.message);
+        assertEquals( clientType != ClientType.OkHttp ? "Read timed out" : "timeout", error.message);
     }
 
     private RecordedThrowable runTest(String urlSpec, ClientType clientType) throws IOException, InterruptedException {
@@ -190,7 +195,9 @@ public class AgentIT {
                     || p.getFileName().toString().equals("slf4j-api.jar")
                     || p.getFileName().toString().equals("jcl-over-slf4j.jar")
                     || p.getFileName().toString().contentEquals("httpclient.jar")
-                    || p.getFileName().toString().contentEquals("httpcore.jar") )
+                    || p.getFileName().toString().contentEquals("httpcore.jar")
+                    || p.getFileName().toString().contentEquals("okhttp.jar")
+                    || p.getFileName().toString().contentEquals("okio.jar") )
             .forEach( p -> elements.add(p.toString()));
         
         return String.join(File.pathSeparator, elements);
diff --git a/url-connection-agent/src/test/java/org/apache/sling/uca/impl/HttpClientLauncher.java b/url-connection-agent/src/test/java/org/apache/sling/uca/impl/HttpClientLauncher.java
index 09ef81f..b4b6117 100644
--- a/url-connection-agent/src/test/java/org/apache/sling/uca/impl/HttpClientLauncher.java
+++ b/url-connection-agent/src/test/java/org/apache/sling/uca/impl/HttpClientLauncher.java
@@ -40,6 +40,10 @@ import org.apache.http.impl.client.CloseableHttpClient;
 import org.apache.http.impl.client.HttpClients;
 import org.apache.http.util.EntityUtils;
 
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+
 /**
  * CLI interface to run HTTP clients
  */
@@ -48,7 +52,8 @@ public class HttpClientLauncher {
     public enum ClientType {
         JavaNet(HttpClientLauncher::runUsingJavaNet), 
         HC3(HttpClientLauncher::runUsingHttpClient3),
-        HC4(HttpClientLauncher::runUsingHttpClient4);
+        HC4(HttpClientLauncher::runUsingHttpClient4),
+        OkHttp(HttpClientLauncher::runUsingOkHttp);
         
         private final HttpConsumer consumer;
 
@@ -163,4 +168,18 @@ public class HttpClientLauncher {
         }
     }
 
+    private static void runUsingOkHttp(String targetUrl) throws IOException {
+        OkHttpClient client = new OkHttpClient();
+        
+        Request request = new Request.Builder()
+            .url(targetUrl)
+            .build();
+
+        try (Response response = client.newCall(request).execute()) {
+            System.out.println("[WEB] " + response.code() + " " + response.message());
+            response.headers().toMultimap().forEach( (n, v) -> {
+                System.out.println("[WEB] " + n + ": " + v);
+            });
+        }
+    }
 }