From 05b97558f5906157193f0096a01e04521d05130f Mon Sep 17 00:00:00 2001 From: Slava Fomin Date: Wed, 22 Nov 2017 23:38:05 +0200 Subject: [PATCH 1/5] Separate global state handler from request tracing --- pom.xml | 2 +- .../littleshoot/proxy/GlobalStateHandler.java | 7 ----- .../proxy/HttpProxyServerBootstrap.java | 15 ++++++++++ .../org/littleshoot/proxy/RequestTracer.java | 18 ++++++++++++ .../proxy/impl/ClientToProxyConnection.java | 16 +++------- .../proxy/impl/DefaultHttpProxyServer.java | 22 ++++++++++++-- .../proxy/impl/ProxyConnection.java | 29 +++++++++++++++++++ 7 files changed, 87 insertions(+), 22 deletions(-) create mode 100644 src/main/java/org/littleshoot/proxy/RequestTracer.java diff --git a/pom.xml b/pom.xml index b25a7d883..2b1eddfe8 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ org.littleshoot littleproxy jar - 1.1.4.0-VGS-SNAPSHOT + 1.1.5.0-VGS-SNAPSHOT LittleProxy LittleProxy is a high performance HTTP proxy written in Java and using the Netty networking framework. diff --git a/src/main/java/org/littleshoot/proxy/GlobalStateHandler.java b/src/main/java/org/littleshoot/proxy/GlobalStateHandler.java index 3c04ffd70..2949f1ffb 100644 --- a/src/main/java/org/littleshoot/proxy/GlobalStateHandler.java +++ b/src/main/java/org/littleshoot/proxy/GlobalStateHandler.java @@ -13,13 +13,6 @@ */ public interface GlobalStateHandler { - /** - * Serializes global state to channel. - * - * @param channel client connection channel - */ - void persistToChannel(Channel channel); - /** * Deserializes global state from channel. * diff --git a/src/main/java/org/littleshoot/proxy/HttpProxyServerBootstrap.java b/src/main/java/org/littleshoot/proxy/HttpProxyServerBootstrap.java index 94a5ec9dc..1c064a140 100644 --- a/src/main/java/org/littleshoot/proxy/HttpProxyServerBootstrap.java +++ b/src/main/java/org/littleshoot/proxy/HttpProxyServerBootstrap.java @@ -211,6 +211,21 @@ HttpProxyServerBootstrap withClientToProxyExHandler( HttpProxyServerBootstrap withProxyToServerExHandler( ExceptionHandler proxyToServerExHandler); + + /** + *

+ * Specify a {@link RequestTracer} to trace proxy requests + *

+ * + *

+ * Default = null + *

+ * + * @param requestTracer + * @return proxy server bootstrap + */ + HttpProxyServerBootstrap withRequestTracer(RequestTracer requestTracer); + /** *

* Specify an {@link GlobalStateHandler} to customize a global state based on channel attributes diff --git a/src/main/java/org/littleshoot/proxy/RequestTracer.java b/src/main/java/org/littleshoot/proxy/RequestTracer.java new file mode 100644 index 000000000..68505e293 --- /dev/null +++ b/src/main/java/org/littleshoot/proxy/RequestTracer.java @@ -0,0 +1,18 @@ +package org.littleshoot.proxy; + +import io.netty.channel.Channel; + +public interface RequestTracer { + + /** + * Start tracing proxy request + * @param channel + */ + void start(Channel channel); + + /** + * Request is served. Finish tracing. + * @param channel + */ + void finish(Channel channel); +} diff --git a/src/main/java/org/littleshoot/proxy/impl/ClientToProxyConnection.java b/src/main/java/org/littleshoot/proxy/impl/ClientToProxyConnection.java index 26161cfa2..a4347e9c7 100644 --- a/src/main/java/org/littleshoot/proxy/impl/ClientToProxyConnection.java +++ b/src/main/java/org/littleshoot/proxy/impl/ClientToProxyConnection.java @@ -4,7 +4,6 @@ import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; -import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPipeline; import io.netty.handler.codec.http.DefaultHttpRequest; import io.netty.handler.codec.http.FullHttpRequest; @@ -771,17 +770,6 @@ protected void exceptionCaught(Throwable cause) { } } - @Override - public void channelRegistered(ChannelHandlerContext ctx) throws Exception { - try { - if (this.proxyServer.getGlobalStateHandler() != null) { - this.proxyServer.getGlobalStateHandler().persistToChannel(ctx.channel()); - } - } finally { - super.channelRegistered(ctx); - } - } - /*************************************************************************** * Connection Management **************************************************************************/ @@ -803,6 +791,10 @@ public void channelRegistered(ChannelHandlerContext ctx) throws Exception { private void initChannelPipeline(ChannelPipeline pipeline) { LOG.debug("Configuring ChannelPipeline"); + if (proxyServer.getRequestTracer() != null) { + pipeline.addLast("requestTracerHandler", new RequestTracerHandler(this)); + } + if (proxyServer.getGlobalStateHandler() != null) { pipeline.addLast("inboundGlobalStateHandler", new InboundGlobalStateHandler(this)); } diff --git a/src/main/java/org/littleshoot/proxy/impl/DefaultHttpProxyServer.java b/src/main/java/org/littleshoot/proxy/impl/DefaultHttpProxyServer.java index cc618d48d..32ad0195f 100644 --- a/src/main/java/org/littleshoot/proxy/impl/DefaultHttpProxyServer.java +++ b/src/main/java/org/littleshoot/proxy/impl/DefaultHttpProxyServer.java @@ -33,6 +33,7 @@ import org.littleshoot.proxy.MitmManagerFactory; import org.littleshoot.proxy.ProxyAuthenticator; import org.littleshoot.proxy.ExceptionHandler; +import org.littleshoot.proxy.RequestTracer; import org.littleshoot.proxy.SslEngineSource; import org.littleshoot.proxy.TransportProtocol; import org.littleshoot.proxy.UnknownTransportProtocolException; @@ -114,6 +115,7 @@ public class DefaultHttpProxyServer implements HttpProxyServer { private final MitmManagerFactory mitmManagerFactory; private final ExceptionHandler clientToProxyExHandler; private final ExceptionHandler proxyToServerExHandler; + private final RequestTracer requestTracer; private final GlobalStateHandler globalStateHandler; private final HttpFiltersSource filtersSource; private final FailureHttpResponseComposer unrecoverableFailureHttpResponseComposer; @@ -250,6 +252,7 @@ private DefaultHttpProxyServer(ServerGroup serverGroup, MitmManagerFactory mitmManagerFactory, ExceptionHandler clientToProxyExHandler, ExceptionHandler proxyToServerExHandler, + RequestTracer requestTracer, GlobalStateHandler globalStateHandler, HttpFiltersSource filtersSource, FailureHttpResponseComposer unrecoverableFailureHttpResponseComposer, @@ -276,6 +279,7 @@ private DefaultHttpProxyServer(ServerGroup serverGroup, this.mitmManagerFactory = mitmManagerFactory; this.clientToProxyExHandler = clientToProxyExHandler; this.proxyToServerExHandler = proxyToServerExHandler; + this.requestTracer = requestTracer; this.globalStateHandler = globalStateHandler; this.filtersSource = filtersSource; this.unrecoverableFailureHttpResponseComposer = unrecoverableFailureHttpResponseComposer; @@ -414,6 +418,7 @@ public HttpProxyServerBootstrap clone() { mitmManagerFactory, clientToProxyExHandler, proxyToServerExHandler, + requestTracer, globalStateHandler, filtersSource, unrecoverableFailureHttpResponseComposer, @@ -605,6 +610,10 @@ protected GlobalStateHandler getGlobalStateHandler() { return globalStateHandler; } + protected RequestTracer getRequestTracer() { + return requestTracer; + } + protected SslEngineSource getSslEngineSource() { return sslEngineSource; } @@ -649,6 +658,7 @@ private static class DefaultHttpProxyServerBootstrap implements HttpProxyServerB private MitmManagerFactory mitmManagerFactory = null; private ExceptionHandler clientToProxyExHandler = null; private ExceptionHandler proxyToServerExHandler = null; + private RequestTracer requestTracer = null; private GlobalStateHandler globalStateHandler = null; private HttpFiltersSource filtersSource = new HttpFiltersSourceAdapter(); private FailureHttpResponseComposer unrecoverableFailureHttpResponseComposer = new DefaultFailureHttpResponseComposer(); @@ -683,6 +693,7 @@ private DefaultHttpProxyServerBootstrap( MitmManagerFactory mitmManagerFactory, ExceptionHandler clientToProxyExHandler, ExceptionHandler proxyToServerExHandler, + RequestTracer requestTracer, GlobalStateHandler globalStateHandler, HttpFiltersSource filtersSource, FailureHttpResponseComposer unrecoverableFailureHttpResponseComposer, @@ -708,6 +719,7 @@ private DefaultHttpProxyServerBootstrap( this.mitmManagerFactory = mitmManagerFactory; this.clientToProxyExHandler = clientToProxyExHandler; this.proxyToServerExHandler = proxyToServerExHandler; + this.requestTracer = requestTracer; this.globalStateHandler = globalStateHandler; this.filtersSource = filtersSource; this.unrecoverableFailureHttpResponseComposer = unrecoverableFailureHttpResponseComposer; @@ -856,6 +868,13 @@ public HttpProxyServerBootstrap withClientToProxyExHandler( return this; } + @Override + public HttpProxyServerBootstrap withRequestTracer( + RequestTracer requestTracer) { + this.requestTracer = requestTracer; + return this; + } + @Override public HttpProxyServerBootstrap withCustomGlobalState( GlobalStateHandler globalStateHandler) { @@ -863,7 +882,6 @@ public HttpProxyServerBootstrap withCustomGlobalState( return this; } - @Override public HttpProxyServerBootstrap withFiltersSource( HttpFiltersSource filtersSource) { @@ -980,7 +998,7 @@ private DefaultHttpProxyServer build() { transportProtocol, determineListenAddress(), sslEngineSource, authenticateSslClients, proxyAuthenticator, chainProxyManager, mitmManagerFactory, - clientToProxyExHandler, proxyToServerExHandler, globalStateHandler, + clientToProxyExHandler, proxyToServerExHandler, requestTracer, globalStateHandler, filtersSource, unrecoverableFailureHttpResponseComposer, transparent, idleConnectionTimeout, activityTrackers, connectTimeout, serverResolver, readThrottleBytesPerSecond, writeThrottleBytesPerSecond, diff --git a/src/main/java/org/littleshoot/proxy/impl/ProxyConnection.java b/src/main/java/org/littleshoot/proxy/impl/ProxyConnection.java index 5c68a8d96..20e9b1777 100644 --- a/src/main/java/org/littleshoot/proxy/impl/ProxyConnection.java +++ b/src/main/java/org/littleshoot/proxy/impl/ProxyConnection.java @@ -743,6 +743,35 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) protected abstract void responseRead(HttpResponse httpResponse); } + @Sharable + protected class RequestTracerHandler extends + ChannelDuplexHandler { + + private final ProxyConnection clientToProxyConnection; + + RequestTracerHandler(ProxyConnection clientToProxyConnection) { + this.clientToProxyConnection = clientToProxyConnection; + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) + throws Exception { + proxyServer.getRequestTracer().start(clientToProxyConnection.channel); + super.channelRead(ctx, msg); + } + + @Override + public void write(ChannelHandlerContext ctx, + Object msg, ChannelPromise promise) + throws Exception { + try { + super.write(ctx, msg, promise); + } finally { + proxyServer.getRequestTracer().finish(clientToProxyConnection.channel); + } + } + } + @Sharable protected class InboundGlobalStateHandler extends ChannelInboundHandlerAdapter { From 85733809e5bafdf9e4757096525f1a78ebd76e9e Mon Sep 17 00:00:00 2001 From: Slava Fomin Date: Thu, 23 Nov 2017 00:13:29 +0200 Subject: [PATCH 2/5] Wraps channel read into finally section --- .../java/org/littleshoot/proxy/impl/ProxyConnection.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/littleshoot/proxy/impl/ProxyConnection.java b/src/main/java/org/littleshoot/proxy/impl/ProxyConnection.java index 20e9b1777..380819aa6 100644 --- a/src/main/java/org/littleshoot/proxy/impl/ProxyConnection.java +++ b/src/main/java/org/littleshoot/proxy/impl/ProxyConnection.java @@ -756,8 +756,11 @@ protected class RequestTracerHandler extends @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - proxyServer.getRequestTracer().start(clientToProxyConnection.channel); - super.channelRead(ctx, msg); + try { + proxyServer.getRequestTracer().start(clientToProxyConnection.channel); + } finally { + super.channelRead(ctx, msg); + } } @Override From 31fe33d979dffb2b4380465d3d4335c18fd77fc4 Mon Sep 17 00:00:00 2001 From: Slava Fomin Date: Thu, 23 Nov 2017 00:16:46 +0200 Subject: [PATCH 3/5] Formatting --- src/main/java/org/littleshoot/proxy/impl/ProxyConnection.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/org/littleshoot/proxy/impl/ProxyConnection.java b/src/main/java/org/littleshoot/proxy/impl/ProxyConnection.java index 380819aa6..13c9f4f90 100644 --- a/src/main/java/org/littleshoot/proxy/impl/ProxyConnection.java +++ b/src/main/java/org/littleshoot/proxy/impl/ProxyConnection.java @@ -744,8 +744,7 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) } @Sharable - protected class RequestTracerHandler extends - ChannelDuplexHandler { + protected class RequestTracerHandler extends ChannelDuplexHandler { private final ProxyConnection clientToProxyConnection; From cf09d0a089f9f6843cef2c9bdb94fb579376d858 Mon Sep 17 00:00:00 2001 From: Slava Fomin Date: Thu, 23 Nov 2017 12:34:18 +0200 Subject: [PATCH 4/5] Adds catch block to request tracer --- .../java/org/littleshoot/proxy/impl/ProxyConnection.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/littleshoot/proxy/impl/ProxyConnection.java b/src/main/java/org/littleshoot/proxy/impl/ProxyConnection.java index 13c9f4f90..5e9926510 100644 --- a/src/main/java/org/littleshoot/proxy/impl/ProxyConnection.java +++ b/src/main/java/org/littleshoot/proxy/impl/ProxyConnection.java @@ -753,10 +753,11 @@ protected class RequestTracerHandler extends ChannelDuplexHandler { } @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) - throws Exception { + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { try { proxyServer.getRequestTracer().start(clientToProxyConnection.channel); + } catch (Throwable t) { + LOG.warn("Unable to start tracing request", t); } finally { super.channelRead(ctx, msg); } @@ -764,8 +765,7 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) @Override public void write(ChannelHandlerContext ctx, - Object msg, ChannelPromise promise) - throws Exception { + Object msg, ChannelPromise promise) throws Exception { try { super.write(ctx, msg, promise); } finally { From f196d126f222f6cfd1df02f97fa4a4c0615da0e4 Mon Sep 17 00:00:00 2001 From: Slava Fomin Date: Thu, 23 Nov 2017 12:38:29 +0200 Subject: [PATCH 5/5] Adds try catch to trace finish method --- .../java/org/littleshoot/proxy/impl/ProxyConnection.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/littleshoot/proxy/impl/ProxyConnection.java b/src/main/java/org/littleshoot/proxy/impl/ProxyConnection.java index 5e9926510..fc2d89b6e 100644 --- a/src/main/java/org/littleshoot/proxy/impl/ProxyConnection.java +++ b/src/main/java/org/littleshoot/proxy/impl/ProxyConnection.java @@ -769,7 +769,11 @@ public void write(ChannelHandlerContext ctx, try { super.write(ctx, msg, promise); } finally { - proxyServer.getRequestTracer().finish(clientToProxyConnection.channel); + try { + proxyServer.getRequestTracer().finish(clientToProxyConnection.channel); + } catch (Throwable t) { + LOG.warn("Unable to finish request tracing", t); + } } } }