Skip to content

Commit b809f6f

Browse files
committed
Log only relevant failures, unless $DEBUG_JVM_HTTP_PROXY_AGENT is set
1 parent 466831b commit b809f6f

File tree

10 files changed

+102
-102
lines changed

10 files changed

+102
-102
lines changed

src/main/java/tech/httptoolkit/javaagent/reactornetty/ReactorNettyResetAllConfigAdvice.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ public class ReactorNettyResetAllConfigAdvice {
2727
public static final Field proxyProviderField;
2828

2929
static {
30-
System.out.println("Running netty reset static initializer");
3130
try {
3231
// Initialize our intercepted SSL provider:
3332
agentSslProvider = SslProvider.builder()

src/main/kotlin/tech/httptoolkit/javaagent/AgentMain.kt

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@ package tech.httptoolkit.javaagent
44

55
import net.bytebuddy.ByteBuddy
66
import net.bytebuddy.agent.builder.AgentBuilder
7+
import net.bytebuddy.description.type.TypeDescription
8+
import net.bytebuddy.dynamic.DynamicType
79
import net.bytebuddy.dynamic.scaffold.TypeValidation
810
import net.bytebuddy.matcher.ElementMatchers.none
11+
import net.bytebuddy.utility.JavaModule
912
import java.lang.instrument.Instrumentation
1013
import javax.net.ssl.SSLContext
1114
import java.net.*
@@ -61,6 +64,9 @@ fun interceptAllHttps(config: Config, instrumentation: Instrumentation) {
6164
setDefaultProxy(proxyHost, proxyPort)
6265
setDefaultSslContext(InterceptedSslContext)
6366

67+
val debugMode = !System.getenv("DEBUG_JVM_HTTP_PROXY_AGENT").isNullOrEmpty()
68+
val logger = TransformationLogger(debugMode)
69+
6470
// Disabling type validation allows us to intercept non-Java types, e.g. Kotlin
6571
// in OkHttp. See https://github.com/raphw/byte-buddy/issues/764
6672
var agentBuilder = AgentBuilder.Default(
@@ -70,20 +76,20 @@ fun interceptAllHttps(config: Config, instrumentation: Instrumentation) {
7076
.with(AgentBuilder.TypeStrategy.Default.REDEFINE)
7177
.with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
7278
.disableClassFormatChanges()
73-
.with(AgentBuilder.Listener.StreamWriting.toSystemOut().withTransformationsOnly())
79+
.with(logger)
7480

7581
arrayOf(
76-
OkHttpClientV3Transformer(),
77-
OkHttpClientV2Transformer(),
78-
ApacheClientRoutingV4Transformer(),
79-
ApacheClientRoutingV5Transformer(),
80-
ApacheSslSocketFactoryTransformer(),
81-
ApacheClientTlsStrategyTransformer(),
82-
JavaClientTransformer(),
83-
JettyClientTransformer(),
84-
AsyncHttpClientConfigTransformer(),
85-
AsyncHttpChannelManagerTransformer(),
86-
ReactorNettyClientConfigTransformer()
82+
OkHttpClientV3Transformer(logger),
83+
OkHttpClientV2Transformer(logger),
84+
ApacheClientRoutingV4Transformer(logger),
85+
ApacheClientRoutingV5Transformer(logger),
86+
ApacheSslSocketFactoryTransformer(logger),
87+
ApacheClientTlsStrategyTransformer(logger),
88+
JavaClientTransformer(logger),
89+
JettyClientTransformer(logger),
90+
AsyncHttpClientConfigTransformer(logger),
91+
AsyncHttpChannelManagerTransformer(logger),
92+
ReactorNettyClientConfigTransformer(logger)
8793
).forEach { matchingAgentTransformer ->
8894
agentBuilder = matchingAgentTransformer.register(agentBuilder)
8995
}
@@ -93,8 +99,19 @@ fun interceptAllHttps(config: Config, instrumentation: Instrumentation) {
9399
println("HTTP Toolkit interception active")
94100
}
95101

96-
interface MatchingAgentTransformer : AgentBuilder.Transformer {
97-
fun register(builder: AgentBuilder): AgentBuilder
102+
abstract class MatchingAgentTransformer(private val logger: TransformationLogger) : AgentBuilder.Transformer {
103+
abstract fun register(builder: AgentBuilder): AgentBuilder
104+
abstract fun transform(builder: DynamicType.Builder<*>): DynamicType.Builder<*>
105+
106+
override fun transform(
107+
builder: DynamicType.Builder<*>,
108+
typeDescription: TypeDescription,
109+
classLoader: ClassLoader?,
110+
module: JavaModule?
111+
): DynamicType.Builder<*> {
112+
logger.beforeTransformation(typeDescription)
113+
return transform(builder)
114+
}
98115
}
99116

100117
private fun setDefaultProxy(proxyHost: String, proxyPort: Int) {

src/main/kotlin/tech/httptoolkit/javaagent/ApacheAsyncClientTransformers.kt renamed to src/main/kotlin/tech/httptoolkit/javaagent/ApacheAsyncClientTransformer.kt

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import tech.httptoolkit.javaagent.apacheclient.ApacheV5ReturnProxyRouteAdvice
1919
// AbstractClientTlsStrategy, which does this, but there's other examples too. We hook upgrade(), so that that
2020
// field is reset to use our context before any client TLS upgrade happens.
2121

22-
class ApacheClientTlsStrategyTransformer : MatchingAgentTransformer {
22+
class ApacheClientTlsStrategyTransformer(logger: TransformationLogger) : MatchingAgentTransformer(logger) {
2323
override fun register(builder: AgentBuilder): AgentBuilder {
2424
return builder
2525
// For v5 we need to hook into every client TlsStrategy (of which there are many).
@@ -42,16 +42,11 @@ class ApacheClientTlsStrategyTransformer : MatchingAgentTransformer {
4242
).transform(this)
4343
}
4444

45-
override fun transform(
46-
builder: DynamicType.Builder<*>,
47-
typeDescription: TypeDescription,
48-
classLoader: ClassLoader?,
49-
module: JavaModule?
50-
): DynamicType.Builder<*>? {
45+
override fun transform(builder: DynamicType.Builder<*>): DynamicType.Builder<*> {
5146
return builder
5247
.visit(
53-
Advice.to(OverrideSslContextFieldAdvice::class.java)
54-
.on(hasMethodName("upgrade"))
55-
);
48+
Advice.to(OverrideSslContextFieldAdvice::class.java)
49+
.on(hasMethodName("upgrade"))
50+
)
5651
}
5752
}

src/main/kotlin/tech/httptoolkit/javaagent/ApacheClientTransformers.kt

Lines changed: 6 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,16 @@ package tech.httptoolkit.javaagent
22

33
import net.bytebuddy.agent.builder.AgentBuilder
44
import net.bytebuddy.asm.Advice
5-
import net.bytebuddy.description.type.TypeDescription
65
import net.bytebuddy.dynamic.DynamicType
76
import net.bytebuddy.matcher.ElementMatchers.*
8-
import net.bytebuddy.utility.JavaModule
97
import tech.httptoolkit.javaagent.apacheclient.ApacheSetSslSocketFactoryAdvice
108
import tech.httptoolkit.javaagent.apacheclient.ApacheV4ReturnProxyRouteAdvice
119
import tech.httptoolkit.javaagent.apacheclient.ApacheV5ReturnProxyRouteAdvice
1210

1311
// For both v4 & v5 we override all implementations of the RoutePlanner interface, and we redefine all routes
1412
// to go via our proxy instead of their existing configuration.
1513

16-
class ApacheClientRoutingV4Transformer : MatchingAgentTransformer {
14+
class ApacheClientRoutingV4Transformer(logger: TransformationLogger) : MatchingAgentTransformer(logger) {
1715
override fun register(builder: AgentBuilder): AgentBuilder {
1816
return builder.type(
1917
hasSuperType(named("org.apache.http.conn.routing.HttpRoutePlanner"))
@@ -22,20 +20,15 @@ class ApacheClientRoutingV4Transformer : MatchingAgentTransformer {
2220
).transform(this)
2321
}
2422

25-
override fun transform(
26-
builder: DynamicType.Builder<*>,
27-
typeDescription: TypeDescription,
28-
classLoader: ClassLoader?,
29-
module: JavaModule?
30-
): DynamicType.Builder<*>? {
23+
override fun transform(builder: DynamicType.Builder<*>): DynamicType.Builder<*> {
3124
return builder.visit(
3225
Advice.to(ApacheV4ReturnProxyRouteAdvice::class.java)
3326
.on(hasMethodName("determineRoute"))
3427
)
3528
}
3629
}
3730

38-
class ApacheClientRoutingV5Transformer : MatchingAgentTransformer {
31+
class ApacheClientRoutingV5Transformer(logger: TransformationLogger) : MatchingAgentTransformer(logger) {
3932
override fun register(builder: AgentBuilder): AgentBuilder {
4033
return builder.type(
4134
hasSuperType(named("org.apache.hc.client5.http.routing.HttpRoutePlanner"))
@@ -44,12 +37,7 @@ class ApacheClientRoutingV5Transformer : MatchingAgentTransformer {
4437
).transform(this)
4538
}
4639

47-
override fun transform(
48-
builder: DynamicType.Builder<*>,
49-
typeDescription: TypeDescription,
50-
classLoader: ClassLoader?,
51-
module: JavaModule?
52-
): DynamicType.Builder<*>? {
40+
override fun transform(builder: DynamicType.Builder<*>): DynamicType.Builder<*> {
5341
return builder.visit(
5442
Advice.to(ApacheV5ReturnProxyRouteAdvice::class.java)
5543
.on(hasMethodName("determineRoute"))
@@ -61,7 +49,7 @@ class ApacheClientRoutingV5Transformer : MatchingAgentTransformer {
6149
// socket is created, the SSL context is replaced with our configured SslSocketFactory that uses our configured
6250
// SSLContext, which trusts our certificate, straight after initialization.
6351

64-
class ApacheSslSocketFactoryTransformer : MatchingAgentTransformer {
52+
class ApacheSslSocketFactoryTransformer(logger: TransformationLogger) : MatchingAgentTransformer(logger) {
6553
override fun register(builder: AgentBuilder): AgentBuilder {
6654
return builder
6755
.type(
@@ -72,12 +60,7 @@ class ApacheSslSocketFactoryTransformer : MatchingAgentTransformer {
7260
).transform(this)
7361
}
7462

75-
override fun transform(
76-
builder: DynamicType.Builder<*>,
77-
typeDescription: TypeDescription,
78-
classLoader: ClassLoader?,
79-
module: JavaModule?
80-
): DynamicType.Builder<*>? {
63+
override fun transform(builder: DynamicType.Builder<*>): DynamicType.Builder<*> {
8164
return builder
8265
.visit(
8366
Advice.to(ApacheSetSslSocketFactoryAdvice::class.java)

src/main/kotlin/tech/httptoolkit/javaagent/AsyncHttpClientConfigTransformers.kt

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,15 @@ package tech.httptoolkit.javaagent
22

33
import net.bytebuddy.agent.builder.AgentBuilder
44
import net.bytebuddy.asm.Advice
5-
import net.bytebuddy.description.type.TypeDescription
65
import net.bytebuddy.dynamic.DynamicType
7-
import net.bytebuddy.utility.JavaModule
86
import net.bytebuddy.matcher.ElementMatchers.*
97
import tech.httptoolkit.javaagent.asynchttpclient.AsyncHttpClientReturnProxySelectorAdvice
108
import tech.httptoolkit.javaagent.asynchttpclient.AsyncHttpClientReturnSslContextAdvice
119
import tech.httptoolkit.javaagent.asynchttpclient.AsyncHttpResetSslEngineFactoryAdvice
1210

1311
// For new clients, we just need to override the properties on the convenient config
1412
// class that contains both proxy & SSL configuration.
15-
class AsyncHttpClientConfigTransformer : MatchingAgentTransformer {
13+
class AsyncHttpClientConfigTransformer(logger: TransformationLogger) : MatchingAgentTransformer(logger) {
1614
override fun register(builder: AgentBuilder): AgentBuilder {
1715
return builder
1816
.type(
@@ -22,12 +20,7 @@ class AsyncHttpClientConfigTransformer : MatchingAgentTransformer {
2220
).transform(this)
2321
}
2422

25-
override fun transform(
26-
builder: DynamicType.Builder<*>,
27-
typeDescription: TypeDescription,
28-
classLoader: ClassLoader?,
29-
module: JavaModule?
30-
): DynamicType.Builder<*>? {
23+
override fun transform(builder: DynamicType.Builder<*>): DynamicType.Builder<*> {
3124
return builder
3225
.visit(Advice.to(AsyncHttpClientReturnSslContextAdvice::class.java)
3326
.on(hasMethodName("getSslContext")))
@@ -38,20 +31,15 @@ class AsyncHttpClientConfigTransformer : MatchingAgentTransformer {
3831

3932
// For existing classes, we need to hook SSL Handler creation, called for
4033
// every new connection
41-
class AsyncHttpChannelManagerTransformer : MatchingAgentTransformer {
34+
class AsyncHttpChannelManagerTransformer(logger: TransformationLogger) : MatchingAgentTransformer(logger) {
4235
override fun register(builder: AgentBuilder): AgentBuilder {
4336
return builder
4437
.type(
4538
named("org.asynchttpclient.netty.channel.ChannelManager")
4639
).transform(this)
4740
}
4841

49-
override fun transform(
50-
builder: DynamicType.Builder<*>,
51-
typeDescription: TypeDescription,
52-
classLoader: ClassLoader?,
53-
module: JavaModule?
54-
): DynamicType.Builder<*>? {
42+
override fun transform(builder: DynamicType.Builder<*>): DynamicType.Builder<*> {
5543
return builder
5644
.visit(Advice.to(AsyncHttpResetSslEngineFactoryAdvice::class.java)
5745
.on(hasMethodName("createSslHandler")))

src/main/kotlin/tech/httptoolkit/javaagent/JavaClientTransformer.kt

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import net.bytebuddy.utility.JavaModule
88
import net.bytebuddy.matcher.ElementMatchers.*
99

1010

11-
class JavaClientTransformer : MatchingAgentTransformer {
11+
class JavaClientTransformer(logger: TransformationLogger): MatchingAgentTransformer(logger) {
1212
override fun register(builder: AgentBuilder): AgentBuilder {
1313
return builder
1414
.type(
@@ -18,12 +18,7 @@ class JavaClientTransformer : MatchingAgentTransformer {
1818
).transform(this)
1919
}
2020

21-
override fun transform(
22-
builder: DynamicType.Builder<*>,
23-
typeDescription: TypeDescription,
24-
classLoader: ClassLoader?,
25-
module: JavaModule?
26-
): DynamicType.Builder<*>? {
21+
override fun transform(builder: DynamicType.Builder<*>): DynamicType.Builder<*> {
2722
return builder
2823
.visit(Advice.to(ReturnProxySelectorAdvice::class.java)
2924
.on(hasMethodName("proxy")))

src/main/kotlin/tech/httptoolkit/javaagent/JettyClientTransformer.kt

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,13 @@ package tech.httptoolkit.javaagent
33
import net.bytebuddy.agent.builder.AgentBuilder
44
import net.bytebuddy.asm.Advice
55
import net.bytebuddy.description.method.MethodDescription
6-
import net.bytebuddy.description.type.TypeDescription
76
import net.bytebuddy.dynamic.DynamicType
8-
import net.bytebuddy.utility.JavaModule
97
import net.bytebuddy.matcher.ElementMatchers.*
108
import org.eclipse.jetty.util.ssl.SslContextFactory
119
import tech.httptoolkit.javaagent.jettyclient.JettyResetDestinationsAdvice
1210
import tech.httptoolkit.javaagent.jettyclient.JettyReturnProxyConfigurationAdvice
1311
import tech.httptoolkit.javaagent.jettyclient.JettyReturnSslContextFactoryV10Advice
1412
import tech.httptoolkit.javaagent.jettyclient.JettyReturnSslContextFactoryV9Advice
15-
import java.util.*
1613

1714
/**
1815
* Transforms the JettyClient to use our proxy & trust our certificate.
@@ -24,7 +21,7 @@ import java.util.*
2421
* (internal connection pools) when resolveDestination is first called
2522
* on each client.
2623
*/
27-
class JettyClientTransformer : MatchingAgentTransformer {
24+
class JettyClientTransformer(logger: TransformationLogger): MatchingAgentTransformer(logger) {
2825

2926
override fun register(builder: AgentBuilder): AgentBuilder {
3027
return builder
@@ -33,12 +30,7 @@ class JettyClientTransformer : MatchingAgentTransformer {
3330
).transform(this)
3431
}
3532

36-
override fun transform(
37-
builder: DynamicType.Builder<*>,
38-
typeDescription: TypeDescription,
39-
classLoader: ClassLoader?,
40-
module: JavaModule?
41-
): DynamicType.Builder<*>? {
33+
override fun transform(builder: DynamicType.Builder<*>): DynamicType.Builder<*> {
4234
return builder
4335
.visit(Advice.to(JettyReturnProxyConfigurationAdvice::class.java)
4436
.on(hasMethodName("getProxyConfiguration")))

src/main/kotlin/tech/httptoolkit/javaagent/OkHttpClientTransformers.kt

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,15 @@ import net.bytebuddy.matcher.ElementMatchers.*
1717
* Without this, proxy settings work by default, but certificates do not - OkHttp
1818
* only trusts the default built-in certificates, and refuses ours.
1919
*/
20-
class OkHttpClientV3Transformer : MatchingAgentTransformer {
20+
class OkHttpClientV3Transformer(logger: TransformationLogger): MatchingAgentTransformer(logger) {
2121
override fun register(builder: AgentBuilder): AgentBuilder {
2222
return builder
2323
.type(
2424
named("okhttp3.OkHttpClient")
2525
).transform(this)
2626
}
2727

28-
override fun transform(
29-
builder: DynamicType.Builder<*>,
30-
typeDescription: TypeDescription,
31-
classLoader: ClassLoader?,
32-
module: JavaModule?
33-
): DynamicType.Builder<*>? {
28+
override fun transform(builder: DynamicType.Builder<*>): DynamicType.Builder<*> {
3429
return builder
3530
// v3 uses proxy() functions, while v4 uses Kotlin getters that compile to the same thing
3631
.visit(Advice.to(ReturnProxyAdvice::class.java)
@@ -52,20 +47,15 @@ class OkHttpClientV3Transformer : MatchingAgentTransformer {
5247
* Without this, proxy settings work by default, but certificates do not - OkHttp
5348
* only trusts the default built-in certificates, and refuses ours.
5449
*/
55-
class OkHttpClientV2Transformer : MatchingAgentTransformer {
50+
class OkHttpClientV2Transformer(logger: TransformationLogger): MatchingAgentTransformer(logger) {
5651
override fun register(builder: AgentBuilder): AgentBuilder {
5752
return builder
5853
.type(
5954
named("com.squareup.okhttp.OkHttpClient")
6055
).transform(this)
6156
}
6257

63-
override fun transform(
64-
builder: DynamicType.Builder<*>,
65-
typeDescription: TypeDescription,
66-
classLoader: ClassLoader?,
67-
module: JavaModule?
68-
): DynamicType.Builder<*>? {
58+
override fun transform(builder: DynamicType.Builder<*>): DynamicType.Builder<*> {
6959
return builder
7060
// v2 uses getX methods:
7161
.visit(Advice.to(ReturnProxyAdvice::class.java)

src/main/kotlin/tech/httptoolkit/javaagent/ReactorNettyTransformers.kt

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import tech.httptoolkit.javaagent.reactornetty.ReactorNettyResetAllConfigAdvice
1414
// that receives the config as part of every single HTTP request - we hook that to reset the relevant
1515
// config props every time they're used.
1616

17-
class ReactorNettyClientConfigTransformer : MatchingAgentTransformer {
17+
class ReactorNettyClientConfigTransformer(logger: TransformationLogger): MatchingAgentTransformer(logger) {
1818
override fun register(builder: AgentBuilder): AgentBuilder {
1919
return builder
2020
.type(
@@ -24,12 +24,7 @@ class ReactorNettyClientConfigTransformer : MatchingAgentTransformer {
2424
).transform(this)
2525
}
2626

27-
override fun transform(
28-
builder: DynamicType.Builder<*>,
29-
typeDescription: TypeDescription,
30-
classLoader: ClassLoader?,
31-
module: JavaModule?
32-
): DynamicType.Builder<*> {
27+
override fun transform(builder: DynamicType.Builder<*>): DynamicType.Builder<*> {
3328
return builder
3429
.visit(Advice.to(ReactorNettyResetAllConfigAdvice::class.java)
3530
.on(isConstructor<MethodDescription>().and(

0 commit comments

Comments
 (0)