Issues building HTTP client / server with Reactor

138 views
Skip to first unread message

Jon Poulton

unread,
Feb 26, 2015, 3:13:40 PM2/26/15
to reactor-...@googlegroups.com
Hi there,
After reading around in here for a bit, I took some advice in another message and built a HTTP client/server based upon the examples
I found in the Reactor unit tests. I am using reactor 2.0.0.M2. I may have made a mistake here, but I can't really see what I've done wrong.

First of all, I have two reactor based services trying to talk to each other via HTTP. One is acting as a server for the other in this 
scenario. I can get both a standard web browser and curl to talk to the server and receive the expected result via GET, so I'm assuming 
the problematic code is in the client. 

I wrote a simple program with a single main() method to try and diagnose what the problem is, using most of code I used in the client. It's
been modified to talk to Google.com on port 80.

----------------------------------------------------------------

import io.netty.channel.ChannelPipeline;
import io.netty.handler.codec.http.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import reactor.Environment;
import reactor.fn.Consumer;
import reactor.io.net.netty.NettyClientSocketOptions;
import reactor.io.net.netty.tcp.NettyTcpClient;
import reactor.io.net.tcp.spec.TcpClientSpec;

/**
 * @author jon poulton
 */
public class TestHttpGet {

    private static final Logger log = LoggerFactory.getLogger(TestHttpGet.class);

    public static void main(String[] args) throws Exception {
        NetClient<DefaultHttpResponse, DefaultFullHttpRequest> netClient = new
                TcpClientSpec<DefaultHttpResponse,DefaultFullHttpRequest>(NettyTcpClient.class)
                .env(new Environment())
                .options(new NettyClientSocketOptions().pipelineConfigurer(new Consumer<ChannelPipeline>(){
                    @Override
                    public void accept(ChannelPipeline pipeline) {
                        pipeline.addLast(new HttpClientCodec());
                    }
                })).connect("google.com", 80).get();
        log.info("Building HTTP request");
        DefaultFullHttpRequest getRequest = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/");
        getRequest.headers().set(HttpHeaders.Names.CONTENT_TYPE, "text/plain");
        getRequest.headers().set(HttpHeaders.Names.CONNECTION, "keep-alive");
        getRequest.headers().set(HttpHeaders.Names.USER_AGENT, "REACTOR-DSO-APPLICATION");
        getRequest.headers().set(HttpHeaders.Names.ACCEPT_CHARSET, "UTF-8");
        getRequest.headers().set(HttpHeaders.Names.HOST, "google.com:80");
        getRequest.headers().set(HttpHeaders.Names.ACCEPT, "[text/plain,application/xml,application/xhtml+xml]");

        NetChannel<DefaultHttpResponse, DefaultFullHttpRequest> connection = netClient.open().await();
        connection.sendAndReceive(getRequest)
                .onSuccess(new Consumer<DefaultHttpResponse>() {
                    @Override
                    public void accept(DefaultHttpResponse resp) {
                        try {
                            log.info("Response was a [{}]", resp.getClass().getCanonicalName());
                            log.info("Full response [{}]", resp);
                        } catch (Exception e) {
                            log.error("Exception occurred", e);
                        }
                    }
                }).await();

        log.info("Should have received response");
        connection.close().await();
        log.info("Closed connection");
        netClient.close().await();
        log.info("Closed client");
    }

}
----------------------------------------------------------------

This gives me a java.lang.ClassCastException saying "io.netty.handler.codec.http.DefaultHttpResponse cannot be cast to 
io.netty.handler.codec.http.DefaultFullHttpResponse".

I don't see this in the "live" client, I think the exception gets swallowed somehow. All that happens is that the onSuccess() block never gets
executed and the whole thing appears to time out, despite the server logs saying that a response was sent. 

If I change the generics such that it uses a DefaultHttpResponse rather than a DefaultFullHttpResponse, then I'm unable to get the any of the content that
was sent back to the client from the server. I know the server sends this content, as I've used curl and a couple of web browsers to verify that it works. 

What is going on here with this client? Can I change it to actually get the content back from a GET? Why does the Promise in the original program simply
fail silently?

Thanks

Jon

Jon Brisbin

unread,
Feb 26, 2015, 4:16:34 PM2/26/15
to Jon Poulton, Reactor Framework
I’m really swamped with issues this week since I’m all by myself. If you can give us a few days, my colleauge will be back and we’ll be able to spend some time trying to figure this out. 

I was having trouble with the HTTP stuff the other trying to do some stuff with etcd. I think we have an issue in there but it’s just going to take us a day or two before we can catch our breaths and take a look at it.


Thanks!

Jon Brisbin
Reactor Project Lead
@j_brisbin | @ProjectReactor

--
You received this message because you are subscribed to the Google Groups "reactor-framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to reactor-framew...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Jon Poulton

unread,
Feb 26, 2015, 4:31:13 PM2/26/15
to reactor-...@googlegroups.com, jsp...@gmail.com
Hi Jon,
Thanks, I really do appreciate the prompt reply. What I'll do for my Demo is rip out the reactor HTTP client side of things, and replace it with a plain-old boring chunk of Apache HTTP client code instead. That will work for now. 

As an addendum to the below (I actually used the "working" class in the code, accidentally): When the generics are such that I'm using a DefaultHttpResponse, it works, but that class doesn't have any methods to allow me to access response content. When I'm using a DefaultFullHttpResponse, I end up with ClassCastExceptions. 

Cheers

Jon
Reply all
Reply to author
Forward
0 new messages