use HttpObjectAggregator conditionally

Viewed 122

Netty version: 4.0.37

I have a requirement to have a netty server which handles both simple JSON requests and also large file uploads. HttpObjectAggregator has a limit of 2 GB for a request size, so I would prefer to use the HttpUploadServer example available here.

So, I want the pipeline to conditionally change depending on the type of request coming in. If it's a POST request, and it's a Multipart type of request, I want the request to be handled by the Upload handler and I want to skip all the rest of the handlers. If not, I want it to pass through the HttpObjectAggregator and then be handled by the Default handler.

I thought of creating one single pipeline looking like this:

HttpRequestDecoder
HttpContentDecompressor
FileUploadHandler <--- My handler to handle file uploads
HttpObjectAggregator 
DefaultHandler <---- My handler to handle normal requests, without file body

And inside the "FileUploadHandler", I added the if else logic like this:

private boolean uploadURL(HttpObject object) {
    HttpRequest request = (HttpRequest) object;
    boolean isMultipart = HttpPostRequestDecoder.isMultipart(request);
    if (request.getMethod().equals(HttpMethod.POST) && isMultipart) {
      // To be handled by file upload handler
      return true;
    }
    return false;
  }

public void channelRead0(ChannelHandlerContext channelHandlerContext,
    HttpObject object) throws Exception {

if (!uploadURL(object)) {
    ReferenceCountUtil.retain(object);
    channelHandlerContext.fireChannelRead(object);
} else {
// Handle the File Upload
....

My objective was to make the UploadHandler "pass on" the message to HttpObjectAggregator IF it's anything other than a POST Multipart request with file body. However, this isn't working for a GET request as the request times out after sometime for lack of a response. I don't entirely understand why this is happening, but my guess is that HttpObjectAggregator is not receiving the initial HttpRequest object from my UploadHandler at all? And that in turn, isn't delivering it to the Default Handler either.

  1. Is my approach wrong? Is there a different way of handling this conditional routing, outside of my Upload Handler?
  2. Can I have any handler before HttpObjectAggregator or should all custom/user handlers come AFTER the HttpObjectAggregator?
1 Answers

I did this by using a Decoder before HttpObjectAggregator. The pipeline looks like:

HttpRequestDecoder
HttpContentDecompressor
RequestURLDecoder <--- New decoder to route requests.
FileUploadHandler <--- My handler to handle file uploads
HttpObjectAggregator 
DefaultHandler <---- My handler to handle normal requests, without file body

The new decoder looks at the request and if it's a POST multipart, dynamically modifies the pipeline to remove the Object aggregator and the default handler. If it's not, then it removes the file upload handler.

(list.add(ReferenceCountUtil.retain(object)) is very important!)

Related