Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added the AcceptHandler feature to the proxy. #321

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
23 changes: 23 additions & 0 deletions src/main/java/org/littleshoot/proxy/AcceptHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package org.littleshoot.proxy;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;

/**
* <p>
* Interface to manage the bytes read the first time after a client
* connection has been accepted.
* </p>
*/
public interface AcceptHandler {

/**
* Process the bytes coming from the first read performed on the
* underlying channel after the connection has been accepted.
* @param bytes
* the bytes read from the underlying channel
* @return the bytes that will be processed by the proxy
*/
ByteBuf process(ChannelHandlerContext ctx, ByteBuf bytes);

}
11 changes: 11 additions & 0 deletions src/main/java/org/littleshoot/proxy/HttpProxyServerBootstrap.java
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,17 @@ HttpProxyServerBootstrap withConnectTimeout(
*/
HttpProxyServerBootstrap withServerResolver(HostResolver serverResolver);

/**
* <p>
* Specify an {@link AcceptHandler} to manage the bytes read the first
* time after a client connection has been accepted.
* </p>
*
* @param acceptHandler
* @return
*/
HttpProxyServerBootstrap withAcceptHandler(AcceptHandler acceptHandler);

/**
* <p>
* Add an {@link ActivityTracker} for tracking activity in this proxy.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
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.DefaultFullHttpResponse;
import io.netty.handler.codec.http.DefaultHttpRequest;
Expand All @@ -25,6 +26,7 @@
import io.netty.util.concurrent.GenericFutureListener;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.littleshoot.proxy.AcceptHandler;
import org.littleshoot.proxy.ActivityTracker;
import org.littleshoot.proxy.FlowContext;
import org.littleshoot.proxy.FullFlowContext;
Expand Down Expand Up @@ -763,6 +765,7 @@ protected void exceptionCaught(Throwable cause) {
private void initChannelPipeline(ChannelPipeline pipeline) {
LOG.debug("Configuring ChannelPipeline");

pipeline.addLast("acceptMonitor", acceptMonitor);
pipeline.addLast("bytesReadMonitor", bytesReadMonitor);
pipeline.addLast("bytesWrittenMonitor", bytesWrittenMonitor);

Expand Down Expand Up @@ -1393,6 +1396,27 @@ protected void setMitming(boolean isMitming) {
this.mitming = isMitming;
}

/***************************************************************************
* Accept tracker
*
* Used to have access to the bytes read from the underlying channel after
* the client connection has been accepted, it is added as the first
* handler of the pipeline and immediately removed after the first read.
**************************************************************************/
private final ByteStreamMonitor acceptMonitor = new ByteStreamMonitor() {
@Override
protected ByteBuf processBytes(ChannelHandlerContext ctx, ByteBuf bytes) {
AcceptHandler acceptHandler = proxyServer.getAcceptHandler();
if (acceptHandler != null) {
ByteBuf processedBytes = acceptHandler.process(ctx, bytes);
ctx.pipeline().remove("acceptMonitor");
return processedBytes;
} else {
return bytes;
}
}
};

/***************************************************************************
* Activity Tracking/Statistics
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import io.netty.handler.traffic.GlobalTrafficShapingHandler;
import io.netty.util.concurrent.GlobalEventExecutor;
import org.apache.commons.io.IOUtils;
import org.littleshoot.proxy.AcceptHandler;
import org.littleshoot.proxy.ActivityTracker;
import org.littleshoot.proxy.ChainedProxyManager;
import org.littleshoot.proxy.DefaultHostResolver;
Expand Down Expand Up @@ -121,6 +122,11 @@ public class DefaultHttpProxyServer implements HttpProxyServer {
*/
private final AtomicBoolean stopped = new AtomicBoolean(false);

/**
* Track the bytes read after the client connection has been accepted.
*/
private final AcceptHandler acceptHandler;

/**
* Track all ActivityTrackers for tracking proxying activity.
*/
Expand Down Expand Up @@ -234,6 +240,7 @@ private DefaultHttpProxyServer(ServerGroup serverGroup,
HttpFiltersSource filtersSource,
boolean transparent,
int idleConnectionTimeout,
AcceptHandler acceptHandler,
Collection<ActivityTracker> activityTrackers,
int connectTimeout,
HostResolver serverResolver,
Expand All @@ -252,6 +259,7 @@ private DefaultHttpProxyServer(ServerGroup serverGroup,
this.filtersSource = filtersSource;
this.transparent = transparent;
this.idleConnectionTimeout = idleConnectionTimeout;
this.acceptHandler = acceptHandler;
if (activityTrackers != null) {
this.activityTrackers.addAll(activityTrackers);
}
Expand Down Expand Up @@ -366,6 +374,7 @@ public HttpProxyServerBootstrap clone() {
filtersSource,
transparent,
idleConnectionTimeout,
acceptHandler,
activityTrackers,
connectTimeout,
serverResolver,
Expand Down Expand Up @@ -549,6 +558,10 @@ protected Collection<ActivityTracker> getActivityTrackers() {
return activityTrackers;
}

protected AcceptHandler getAcceptHandler() {
return acceptHandler;
}

public String getProxyAlias() {
return proxyAlias;
}
Expand All @@ -574,6 +587,7 @@ private static class DefaultHttpProxyServerBootstrap implements HttpProxyServerB
private HttpFiltersSource filtersSource = new HttpFiltersSourceAdapter();
private boolean transparent = false;
private int idleConnectionTimeout = 70;
private AcceptHandler acceptHandler;
private Collection<ActivityTracker> activityTrackers = new ConcurrentLinkedQueue<ActivityTracker>();
private int connectTimeout = 40000;
private HostResolver serverResolver = new DefaultHostResolver();
Expand All @@ -599,6 +613,7 @@ private DefaultHttpProxyServerBootstrap(
MitmManager mitmManager,
HttpFiltersSource filtersSource,
boolean transparent, int idleConnectionTimeout,
AcceptHandler acceptHandler,
Collection<ActivityTracker> activityTrackers,
int connectTimeout, HostResolver serverResolver,
long readThrottleBytesPerSecond,
Expand All @@ -617,6 +632,7 @@ private DefaultHttpProxyServerBootstrap(
this.filtersSource = filtersSource;
this.transparent = transparent;
this.idleConnectionTimeout = idleConnectionTimeout;
this.acceptHandler = acceptHandler;
if (activityTrackers != null) {
this.activityTrackers.addAll(activityTrackers);
}
Expand Down Expand Up @@ -781,6 +797,12 @@ public HttpProxyServerBootstrap withServerResolver(
return this;
}

@Override
public HttpProxyServerBootstrap withAcceptHandler(AcceptHandler acceptHandler) {
this.acceptHandler = acceptHandler;
return this;
}

@Override
public HttpProxyServerBootstrap plusActivityTracker(
ActivityTracker activityTracker) {
Expand Down Expand Up @@ -823,7 +845,7 @@ transportProtocol, determineListenAddress(),
sslEngineSource, authenticateSslClients,
proxyAuthenticator, chainProxyManager, mitmManager,
filtersSource, transparent,
idleConnectionTimeout, activityTrackers, connectTimeout,
idleConnectionTimeout, acceptHandler, activityTrackers, connectTimeout,
serverResolver, readThrottleBytesPerSecond, writeThrottleBytesPerSecond,
localAddress, proxyAlias);
}
Expand Down
25 changes: 25 additions & 0 deletions src/main/java/org/littleshoot/proxy/impl/ProxyConnection.java
Original file line number Diff line number Diff line change
Expand Up @@ -696,6 +696,31 @@ public void channelRead(ChannelHandlerContext ctx, Object msg)
protected abstract void bytesRead(int numberOfBytes);
}

/**
* Utility handler for monitoring byte streams on this connection.
*/
@Sharable
protected abstract class ByteStreamMonitor extends
ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg)
throws Exception {
Object processedMsg = msg;

try {
if (msg instanceof ByteBuf) {
processedMsg = processBytes(ctx, (ByteBuf) msg);
}
} catch (Throwable t) {
LOG.warn("Unable to call processBytes", t);
} finally {
super.channelRead(ctx, processedMsg);
}
}

protected abstract ByteBuf processBytes(ChannelHandlerContext ctx, ByteBuf bytes);
}

/**
* Utility handler for monitoring requests read on this connection.
*/
Expand Down