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());
}
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());
} catch (Exception e) {
log.error("Exception occurred", e);
}
}
}).await();
log.info("Should have received response");
connection.close().await();
netClient.close().await();
}
}
----------------------------------------------------------------
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