Skip to content
This repository was archived by the owner on Feb 24, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<groupId>org.littleshoot</groupId>
<artifactId>littleproxy</artifactId>
<packaging>jar</packaging>
<version>1.1.4.0-VGS-SNAPSHOT</version>
<version>1.1.5.0-VGS-SNAPSHOT</version>
<name>LittleProxy</name>
<description>
LittleProxy is a high performance HTTP proxy written in Java and using the Netty networking framework.
Expand Down
7 changes: 0 additions & 7 deletions src/main/java/org/littleshoot/proxy/GlobalStateHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,21 @@ HttpProxyServerBootstrap withClientToProxyExHandler(
HttpProxyServerBootstrap withProxyToServerExHandler(
ExceptionHandler proxyToServerExHandler);


/**
* <p>
* Specify a {@link RequestTracer} to trace proxy requests
* </p>
*
* <p>
* Default = null
* </p>
*
* @param requestTracer
* @return proxy server bootstrap
*/
HttpProxyServerBootstrap withRequestTracer(RequestTracer requestTracer);

/**
* <p>
* Specify an {@link GlobalStateHandler} to customize a global state based on channel attributes
Expand Down
18 changes: 18 additions & 0 deletions src/main/java/org/littleshoot/proxy/RequestTracer.java
Original file line number Diff line number Diff line change
@@ -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);
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
**************************************************************************/
Expand All @@ -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));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -250,6 +252,7 @@ private DefaultHttpProxyServer(ServerGroup serverGroup,
MitmManagerFactory mitmManagerFactory,
ExceptionHandler clientToProxyExHandler,
ExceptionHandler proxyToServerExHandler,
RequestTracer requestTracer,
GlobalStateHandler globalStateHandler,
HttpFiltersSource filtersSource,
FailureHttpResponseComposer unrecoverableFailureHttpResponseComposer,
Expand All @@ -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;
Expand Down Expand Up @@ -414,6 +418,7 @@ public HttpProxyServerBootstrap clone() {
mitmManagerFactory,
clientToProxyExHandler,
proxyToServerExHandler,
requestTracer,
globalStateHandler,
filtersSource,
unrecoverableFailureHttpResponseComposer,
Expand Down Expand Up @@ -605,6 +610,10 @@ protected GlobalStateHandler getGlobalStateHandler() {
return globalStateHandler;
}

protected RequestTracer getRequestTracer() {
return requestTracer;
}

protected SslEngineSource getSslEngineSource() {
return sslEngineSource;
}
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -683,6 +693,7 @@ private DefaultHttpProxyServerBootstrap(
MitmManagerFactory mitmManagerFactory,
ExceptionHandler clientToProxyExHandler,
ExceptionHandler proxyToServerExHandler,
RequestTracer requestTracer,
GlobalStateHandler globalStateHandler,
HttpFiltersSource filtersSource,
FailureHttpResponseComposer unrecoverableFailureHttpResponseComposer,
Expand All @@ -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;
Expand Down Expand Up @@ -856,14 +868,20 @@ public HttpProxyServerBootstrap withClientToProxyExHandler(
return this;
}

@Override
public HttpProxyServerBootstrap withRequestTracer(
RequestTracer requestTracer) {
this.requestTracer = requestTracer;
return this;
}

@Override
public HttpProxyServerBootstrap withCustomGlobalState(
GlobalStateHandler globalStateHandler) {
this.globalStateHandler = globalStateHandler;
return this;
}


@Override
public HttpProxyServerBootstrap withFiltersSource(
HttpFiltersSource filtersSource) {
Expand Down Expand Up @@ -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,
Expand Down
35 changes: 35 additions & 0 deletions src/main/java/org/littleshoot/proxy/impl/ProxyConnection.java
Original file line number Diff line number Diff line change
Expand Up @@ -743,6 +743,41 @@ public void channelRead(ChannelHandlerContext ctx, Object msg)
protected abstract void responseRead(HttpResponse httpResponse);
}

@Sharable
protected class RequestTracerHandler extends ChannelDuplexHandler {

private final ProxyConnection<HttpRequest> clientToProxyConnection;

RequestTracerHandler(ProxyConnection<HttpRequest> clientToProxyConnection) {
this.clientToProxyConnection = clientToProxyConnection;
}

@Override
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);
}
}

@Override
public void write(ChannelHandlerContext ctx,
Object msg, ChannelPromise promise) throws Exception {
try {
super.write(ctx, msg, promise);
} finally {
try {
proxyServer.getRequestTracer().finish(clientToProxyConnection.channel);
} catch (Throwable t) {
LOG.warn("Unable to finish request tracing", t);
}
}
}
}

@Sharable
protected class InboundGlobalStateHandler extends
ChannelInboundHandlerAdapter {
Expand Down