Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HTTP Request using Netty

I have just started netty and I am really disappointed with the documentation present on their website.

I am trying to connect to an URL using Netty.. I took the time client example from their website and changed it as per my requirement..

Code :

public class NettyClient {

      public static void main(String[] args) throws Exception {
          String host = "myUrl.com/v1/parma?param1=value";
            int port = 443;
            EventLoopGroup workerGroup = new NioEventLoopGroup();

            try {
                Bootstrap b = new Bootstrap();             
                b.group(workerGroup); 
                b.channel(NioSocketChannel.class); 
                b.option(ChannelOption.SO_KEEPALIVE, true); 
                b.handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    public void initChannel(SocketChannel ch) throws Exception {
                        ch.pipeline().addLast(new ClientHandler());
                        ch.pipeline().addLast("encoder", new HttpRequestEncoder());
                    }
                });

                // Start the client.
                ChannelFuture f = b.connect(host, port).sync(); 

                // Wait until the connection is closed.
                f.channel().closeFuture().sync();
            } finally {
                workerGroup.shutdownGracefully();
            }
        }
}

But the problem is that that it expects only the url without the query parameters.. How can I pass query parameters with the URL? and please provide me some link of a good documentation for Netty 4..

EDIT

Client code after referring the example mentioned in the answer :

URI uri = new URI("myUrl.com/v1/parma?param1=value");          
           String scheme = uri.getScheme() == null? "http" : uri.getScheme();
           String host = "myUrl.com";
            int port = 443;



            boolean ssl = "https".equalsIgnoreCase(scheme);

         // Configure the client.
            EventLoopGroup group = new NioEventLoopGroup();
            try {
                Bootstrap b = new Bootstrap();
                b.group(group)
                 .channel(NioSocketChannel.class)
                 .handler(new NettyClientInitializer(ssl));
                // Make the connection attempt.
                Channel ch = b.connect(host, port).sync().channel();
                // Prepare the HTTP request.
                HttpRequest request = new DefaultHttpRequest(
                        HttpVersion.HTTP_1_1, HttpMethod.GET, uri.getRawPath());
                request.headers().set(HttpHeaders.Names.HOST, host);
                request.headers().set(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.CLOSE);
                //request.headers().set(HttpHeaders.Names.ACCEPT_ENCODING, HttpHeaders.Values.GZIP);

                /*// Set some example cookies.
                request.headers().set(
                        HttpHeaders.Names.COOKIE,
                        ClientCookieEncoder.encode(
                                new DefaultCookie("my-cookie", "foo"),
                                new DefaultCookie("another-cookie", "bar")));
*/
                // Send the HTTP request.
                ch.writeAndFlush(request);

                // Wait for the server to close the connection.
                ch.closeFuture().sync();
            } finally {
                // Shut down executor threads to exit.
                group.shutdownGracefully();
            }

handler code :

public class ClientHandler extends SimpleChannelInboundHandler<HttpObject> {

    @Override
    public void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
        if (msg instanceof HttpResponse) {
            HttpResponse response = (HttpResponse) msg;

            System.out.println("STATUS: " + response.getStatus());
            System.out.println("VERSION: " + response.getProtocolVersion());
            System.out.println();

            if (!response.headers().isEmpty()) {
                for (String name: response.headers().names()) {
                    for (String value: response.headers().getAll(name)) {
                        System.out.println("HEADER: " + name + " = " + value);
                    }
                }
                System.out.println();
            }

            if (HttpHeaders.isTransferEncodingChunked(response)) {
                System.out.println("CHUNKED CONTENT {");
            } else {
                System.out.println("CONTENT {");
            }
        }
        if (msg instanceof HttpContent) {
            HttpContent content = (HttpContent) msg;

            System.out.print(content.content().toString(CharsetUtil.UTF_8));
            System.out.flush();

            if (content instanceof LastHttpContent) {
                System.out.println("} END OF CONTENT");
            }
        }
    }

    @Override
    public void exceptionCaught(
            ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }


}

initializer code :

public class NettyClientInitializer extends ChannelInitializer<SocketChannel> {

    private final boolean ssl;

    public NettyClientInitializer(boolean ssl) {
        this.ssl = ssl;
    }

    @Override
    public void initChannel(SocketChannel ch) throws Exception {
        // Create a default pipeline implementation.
        ChannelPipeline p = ch.pipeline();

        p.addLast("log", new LoggingHandler(LogLevel.INFO));
        // Enable HTTPS if necessary.
        /*
        if (ssl) {
            SSLEngine engine =
                SecureChatSslContextFactory.getClientContext().createSSLEngine();
            engine.setUseClientMode(true);

            p.addLast("ssl", new SslHandler(engine));
        }
*/
        p.addLast("codec", new HttpClientCodec());

        // Remove the following line if you don't want automatic content decompression.
       // p.addLast("inflater", new HttpContentDecompressor());

        // Uncomment the following line if you don't want to handle HttpChunks.
        p.addLast("aggregator", new HttpObjectAggregator(1048576));
        p.addLast("handler", new ClientHandler());
    }
}
like image 834
Mitaksh Gupta Avatar asked Nov 18 '13 06:11

Mitaksh Gupta


2 Answers

Your code only handles the low-level connection at the moment. Indeed at this level only the hostname and port can be used.

For the HTTP request You have to construct an HttpRequest object and send it over the channel. In this request object You define the query parameters and all such things.

There is a bunch of example code about HTTP client functionality on Netty website - have a a look!

like image 111
Tarmo R Avatar answered Nov 12 '22 17:11

Tarmo R


In this example the problem lies with the constructor for the DefaultHttpRequest parameter of uri.getRawPath(). The invocation of this method does NOT return the query parameters. It works in this case as there were no query parameters in the Snoop example. By substituting uri.toASCIIString() returns the encoded uri complete with the query parameters. To prove this to yourself, rather than having a method invocation within a method invocation (a bad idea for just this reason, add the statement

String url = uri.getRawPath();

and look at the string url.

I had the exact same problem. I've done this natively in servlets for years but now was trying to do it in a Netty app.

Consequently the new code would be:

String path = uri.toASCIIString();
// Prepare the HTTP request.
HttpRequest request = new DefaultFullHttpRequest(
        HttpVersion.HTTP_1_1, HttpMethod.GET, path);
like image 3
Walt Corey Avatar answered Nov 12 '22 19:11

Walt Corey