Skip to content

Instantly share code, notes, and snippets.

@rhart
Last active February 25, 2016 16:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rhart/459d25a303087262e6c4 to your computer and use it in GitHub Desktop.
Save rhart/459d25a303087262e6c4 to your computer and use it in GitHub Desktop.
import io.netty.bootstrap.Bootstrap
import io.netty.buffer.ByteBuf
import io.netty.channel.ChannelFuture
import io.netty.channel.ChannelHandlerContext
import io.netty.channel.ChannelInitializer
import io.netty.channel.ChannelPipeline
import io.netty.channel.SimpleChannelInboundHandler
import io.netty.channel.socket.SocketChannel
import io.netty.handler.codec.http.DefaultFullHttpResponse
import io.netty.handler.codec.http.HttpResponseStatus
import io.netty.handler.codec.http.HttpVersion
import ratpack.util.internal.ChannelImplDetector
import static ratpack.groovy.Groovy.ratpack
ratpack {
handlers {
all {
context.byMethod {
named("CONNECT") {
def clientProxyConnection = directChannelAccess.channel
// setup TCP client
Bootstrap b = new Bootstrap()
b.group(clientProxyConnection.eventLoop())
.channel(ChannelImplDetector.getSocketChannelImpl())
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline p = ch.pipeline();
p.addLast(new SimpleChannelInboundHandler<ByteBuf>() {
@Override
protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {
println "target server response received"
msg.retain()
clientProxyConnection.writeAndFlush(msg)
}
})
}
})
// connect to proxy target server
ChannelFuture proxyServerConnection = b.connect("google.com", 443);
proxyServerConnection.addListener {
if (proxyServerConnection.success) {
// can connect to target server so reply to CONNECT request
clientProxyConnection.pipeline().remove("decoder")
clientProxyConnection.writeAndFlush(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK))
clientProxyConnection.pipeline().remove("encoder")
clientProxyConnection.pipeline().remove("deflater")
clientProxyConnection.pipeline().remove("chunkedWriter")
}
}
// take over the client -> proxy channel to forward future tcp messages
directChannelAccess.takeOwnership { proxyMessage ->
println "new proxy message"
proxyServerConnection.channel().writeAndFlush(proxyMessage)
}
}
}
}
}
}
@pledbrook
Copy link

It seems from this code that you need to add Connection, Proxy-Connection and Via headers to the initial response to the CONNECT request.

@rhart
Copy link
Author

rhart commented Feb 25, 2016

Ahh ok, will try that.

Interestingly it did appear that I was getting messages after sending back the connect. Well, a single message. And after passing that on to the target server I get 4 responses which I send back. The problem I thought I had is that I'm not terminating anywhere.

@rhart
Copy link
Author

rhart commented Feb 25, 2016

There's a slight update to remove the rest of the http related parts of the pipeline after the CONNECT response

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment