Skip to content

Commit fb3a969

Browse files
davidhsvDavid Vieira
authored andcommitted
Fix Apache Http Client interception bug when creating an anonymous class of SSLConnectionSocketFactory. When creating an anonymous class getDeclaredField will not return the needed socketFactory attribute. This is the behavior of RestEasy for some cases, see https://github.com/resteasy/Resteasy/blob/main/resteasy-client/src/main/java/org/jboss/resteasy/client/jaxrs/engines/ClientHttpEngineBuilder43.java#L128
1 parent 459b931 commit fb3a969

File tree

4 files changed

+50
-2
lines changed

4 files changed

+50
-2
lines changed

src/main/java/tech/httptoolkit/javaagent/advice/apacheclient/ApacheSetSslSocketFactoryAdvice.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
import javax.net.ssl.SSLContext;
66
import java.lang.reflect.Field;
7-
import java.security.NoSuchAlgorithmException;
87
import java.util.Arrays;
98

109
public class ApacheSetSslSocketFactoryAdvice {
@@ -17,7 +16,7 @@ public static void beforeCreateSocket(@Advice.This Object thisFactory) throws Ex
1716
for (String factoryFieldName : Arrays.asList("socketfactory", "socketFactory")) {
1817
try {
1918
// Detect which field(s) are present on this class
20-
Field field = thisFactory.getClass().getDeclaredField(factoryFieldName);
19+
Field field = getDeclaredFieldInClassTree(thisFactory.getClass(), factoryFieldName);
2120

2221
// Allow ourselves to change the socket factory value
2322
field.setAccessible(true);
@@ -32,4 +31,14 @@ public static void beforeCreateSocket(@Advice.This Object thisFactory) throws Ex
3231
throw new IllegalStateException("Apache HttpClient interception setup failed");
3332
}
3433
}
34+
35+
public static Field getDeclaredFieldInClassTree(Class<?> type, String fieldName) throws NoSuchFieldException {
36+
for (Class<?> clazz = type; clazz != null; clazz = clazz.getSuperclass()) {
37+
try {
38+
return clazz.getDeclaredField(fieldName);
39+
} catch (NoSuchFieldException ignored) { }
40+
}
41+
throw new NoSuchFieldException();
42+
}
43+
3544
}

test-app/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ dependencies {
3535

3636
implementation group: 'io.vertx', name: 'vertx-core', version: '4.2.2'
3737
implementation group: 'io.vertx', name: 'vertx-web-client', version: '4.2.2'
38+
39+
implementation group: 'org.jboss.resteasy', name: 'resteasy-client', version: '4.7.4.Final'
3840
}
3941

4042
test {

test-app/src/main/java/tech/httptoolkit/testapp/Main.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ public class Main {
1717
private static final Map<String, ClientCase<?>> cases = Map.ofEntries(
1818
entry("apache-v3", new ApacheHttpClientV3Case()),
1919
entry("apache-v4", new ApacheHttpClientV4Case()),
20+
entry("rest-easy-with-apache-v4", new RestEasyWithApacheHttpClientV4Case()),
2021
entry("apache-v5", new ApacheHttpClientV5Case()),
2122
entry("apache-async-v4", new ApacheHttpAsyncClientV4Case()),
2223
entry("apache-async-v5", new ApacheHttpAsyncClientV5Case()),
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package tech.httptoolkit.testapp.cases;
2+
3+
import org.jboss.resteasy.client.jaxrs.ResteasyClient;
4+
import org.jboss.resteasy.client.jaxrs.engines.ClientHttpEngineBuilder43;
5+
import org.jboss.resteasy.client.jaxrs.internal.ResteasyClientBuilderImpl;
6+
7+
import javax.net.ssl.SSLContext;
8+
import java.io.IOException;
9+
import java.net.MalformedURLException;
10+
import java.net.URI;
11+
import java.security.NoSuchAlgorithmException;
12+
13+
public class RestEasyWithApacheHttpClientV4Case extends ClientCase<ResteasyClient> {
14+
15+
@Override
16+
public ResteasyClient newClient(String url) throws MalformedURLException {
17+
ResteasyClientBuilderImpl resteasyClientBuilder = new ResteasyClientBuilderImpl();
18+
resteasyClientBuilder.sslContext(getSslContext());
19+
resteasyClientBuilder.httpEngine(new ClientHttpEngineBuilder43()
20+
.resteasyClientBuilder(resteasyClientBuilder).build());
21+
return resteasyClientBuilder.build();
22+
}
23+
24+
@Override
25+
public int test(String url, ResteasyClient resteasyClient) throws IOException {
26+
return resteasyClient.target(URI.create(url)).request().get().getStatus();
27+
}
28+
29+
private SSLContext getSslContext() {
30+
try {
31+
return SSLContext.getDefault();
32+
} catch (NoSuchAlgorithmException e) {
33+
throw new IllegalStateException(e);
34+
}
35+
}
36+
}

0 commit comments

Comments
 (0)