package de.ganskef.test; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.channel.EventLoopGroup; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.HttpClientCodec; import io.netty.handler.codec.http.HttpContent; import io.netty.handler.codec.http.HttpContentDecompressor; import io.netty.handler.codec.http.HttpHeaders; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpObject; import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.HttpVersion; import io.netty.handler.codec.http.LastHttpContent; import io.netty.handler.logging.LogLevel; import io.netty.handler.logging.LoggingHandler; import io.netty.handler.ssl.SslContext; import io.netty.handler.ssl.util.InsecureTrustManagerFactory; import java.io.File; import java.io.RandomAccessFile; import java.net.URI; import java.nio.channels.FileChannel; import org.apache.commons.io.IOUtils; public class NettyClient_NoHttps implements IClient { public File get(String url, IProxy proxy, String target) throws Exception { return get(new URI(url), url, "127.0.0.1", proxy.getProxyPort(), target); } public File get(String url, IProxy proxy) throws Exception { return get(new URI(url), url, "127.0.0.1", proxy.getProxyPort(), "proxy.out"); } public File get(String url) throws Exception { return get(url, "client.out"); } public File get(String url, String target) throws Exception { URI uri = new URI(url); String host = uri.getHost(); int port = uri.getPort(); if (port == -1) { if (isSecured(uri)) { port = 443; } else { port = 80; } } return get(uri, uri.getRawPath(), host, port, target); } private boolean isSecured(URI uri) { // XXX https via offline proxy won't work with this client. I mean, this // was my experience while debugging it. I had no success with Apache // HC, too. Only URLConnection works like expected for me. // // It seems to me we have to wait for a proper solution - see: // https://github.com/netty/netty/issues/1133#event-299614098 // normanmaurer modified the milestone: 4.1.0.Beta5, 4.1.0.Beta6 // // return uri.getScheme().equalsIgnoreCase("https"); return false; } private File get(URI uri, String url, String proxyHost, int proxyPort, final String target) throws Exception { final SslContext sslCtx; if (isSecured(uri)) { sslCtx = SslContext .newClientContext(InsecureTrustManagerFactory.INSTANCE); } else { sslCtx = null; } final NettyClientHandler handler = new NettyClientHandler(target); EventLoopGroup group = new NioEventLoopGroup(); try { Bootstrap b = new Bootstrap(); b.group(group).channel(NioSocketChannel.class) .handler(new NettyClientInitializer(sslCtx, handler)); // .handler(new HttpSnoopClientInitializer(sslCtx)); Channel ch = b.connect(proxyHost, proxyPort).sync().channel(); HttpRequest request = new DefaultFullHttpRequest( HttpVersion.HTTP_1_1, HttpMethod.GET, url); request.headers().set(HttpHeaders.Names.HOST, uri.getHost()); request.headers().set(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.CLOSE); request.headers().set(HttpHeaders.Names.ACCEPT_ENCODING, HttpHeaders.Values.GZIP); ch.writeAndFlush(request); ch.closeFuture().sync(); } finally { group.shutdownGracefully(); } return handler.getFile(); } } class NettyClientHandler extends SimpleChannelInboundHandler<HttpObject> { private File file; public NettyClientHandler(String target) { File dir = new File("src/test/resources/tmp"); dir.mkdirs(); file = new File(dir, target); file.delete(); } @Override protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception { if (msg instanceof HttpContent) { HttpContent content = (HttpContent) msg; RandomAccessFile output = null; FileChannel oc = null; try { output = new RandomAccessFile(file, "rw"); oc = output.getChannel(); oc.position(oc.size()); ByteBuf buffer = content.content(); for (int i = 0, len = buffer.nioBufferCount(); i < len; i++) { oc.write(buffer.nioBuffers()[i]); } } finally { IOUtils.closeQuietly(oc); IOUtils.closeQuietly(output); } if (content instanceof LastHttpContent) { ctx.close(); } } } public File getFile() { return file; } } class NettyClientInitializer extends ChannelInitializer<SocketChannel> { private ChannelHandler handler; private SslContext sslCtx; public NettyClientInitializer(SslContext sslCtx, ChannelHandler handler) { this.sslCtx = sslCtx; this.handler = handler; } @Override protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline p = ch.pipeline(); if (sslCtx != null) { p.addLast(sslCtx.newHandler(ch.alloc())); } p.addLast("log", new LoggingHandler(LogLevel.TRACE)); p.addLast("codec", new HttpClientCodec()); p.addLast("inflater", new HttpContentDecompressor()); // p.addLast("aggregator", new HttpObjectAggregator(10 * 1024 * 1024)); p.addLast("handler", handler); } }