Reputation: 836
I'm currently using Netty 4.0 if that matters but anyways..
I have a handler written like so that I want to filter out requests depending on the URI:
public class URIFilterHandler extends SimpleChannelInboundHandler<HttpRequest> {
public void channelRead0(ChannelHandlerContext ctx, HttpRequest req) {
String uri = req.uri();
if (uri.contains("abcde")) {
HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.NO_CONTENT);
ctx.writeAndFlush(response);
// HERE IS WHERE I WANT TO SKIP REST OF THE HANDLERS
} else {
ctx.fireChannelRead(req);
}
}
}
And then here is my pipeline
public class ServerInitializer extends ChannelInitializer<SocketChannel> {
@Override
public void initChannel(SocketChannel ch) {
ChannelPipeline p = ch.pipeline();
p.addLast(new HttpRequestDecoder());
p.addLast(new HttpResponseEncoder());
p.addLast(new URIFilterHandler());
p.addLast(new HttpObjectAggregator(1048576));
p.addLast(new RequestHandler());
}
}
I tried the following, but it seemed to permanently remove these handlers from the pipeline and not just for the one request.
ctx.pipeline().remove(HttpObjectAggregator.class);
ctx.pipeline().remove(RequestHandler.class;)
I tried using ctx.channel().close() and ctx.fireChannelInactive() to no avail. It seems to still pass the request onto the next handler (HttpObjectAggregator in this case). I think it's possibly being due to the close() and fireChannelInactive() being asynchronous?
EDIT: It seems the issue I was having was I was sending back a DefaultHttpResponse. When I sent back a DefaultFullHttpResponse, the request never hangs.
Upvotes: 2
Views: 3616
Reputation: 2978
To skip the rest of the handlers, just do nothing. To continue to handle data with the next handler, with the initial object or with one another, call ctx.fireChannelRead( object )
Take care of reference counted objects. SimpleChannelInboundHandler
release by default the input (depending on constructor parameters). If you decide to fire it to the next handler, you must call ReferenceCountUtil.retain(Object)
.
See documentation here: http://netty.io/wiki/reference-counted-objects.html
Moreover, I think you should put the HttpObjectAggregator
handler before your own handler on pipeline, and make your handler catching FullHttpRequest
.
HttpObjectAggregator
handles all http chuncks for you and puts on pipeline a FullHttpRequest
. In your case, it may be interessing because if you ignore one chunck, what do you do with others chuncks already aggregated on pipeline ? I guess you may have a DecoderException thrown if you do nothing.
Upvotes: 5
Reputation: 12817
If you don't call ctx.fireChannelRead()
in channelRead0
, then the message will not be propagated to the following handlers. This can be demonstrated with the following code snippet, where the first handler filters out all odd numbers:
EmbeddedChannel channel = new EmbeddedChannel(
new SimpleChannelInboundHandler<Integer>() {
@Override
protected void channelRead0(ChannelHandlerContext ctx,
Integer msg) throws Exception {
if (msg % 2 == 0)
ctx.fireChannelRead(msg);
}
},
new ChannelInboundHandlerAdapter() {
@Override
public void channelRead(ChannelHandlerContext ctx,
Object msg) throws Exception {
System.out.println(msg);
}
});
channel.writeInbound(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Upvotes: 2