0

I have created an HTTPServer in Netty with the following handler:

public class HttpRouterServerHandler extends SimpleChannelInboundHandler<HttpRequest> {

public void channelRead0(ChannelHandlerContext ctx, HttpRequest req) {
  if (HttpUtil.is100ContinueExpected(req)) {
     ctx.writeAndFlush(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.CONTINUE));
     return;
  }

  System.out.println(req.toString());
  HttpResponse res = /* create the response here */      
  flushResponse(ctx, req, res);
}

I send the PUT request in Python using http.client:

     json_data = /* constructJSON content */
     connection = http.client.HTTPConnection("localhost", 8080)
     connection.request("PUT", "/proto/api/send", json_data)     
     response = self.connection.getresponse()
     connection.close()

For some reason, I can't get the BODY of the request (the json content). The reason seems to be that my HttpRequest is not a FullHttpRequest, so I can't get its content()

It I print the content of my request, I have something like:

DefaultHttpRequest(decodeResult: success, version: HTTP/1.1)
PUT /proto/api/send HTTP/1.1
Host: localhost:8080
Accept-Encoding: identity
content-length: 47

Also I tried to replace the HttpRequest by FullHttpRequest for my handler, but in this case the Netty server does not respond anymore, which lead to an exception in Python:

public class HttpRouterServerHandler extends SimpleChannelInboundHandler<FullHttpRequest> {

  public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest req) {
    if (HttpUtil.is100ContinueExpected(req)) {
       ctx.writeAndFlush(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.CONTINUE));
    return;
  } 

   System.out.println(req.toString());
   HttpResponse res = /* create the response here */      
   flushResponse(ctx, req, res);
}

Where is my mistake?

Hervé Girod
  • 465
  • 3
  • 12

2 Answers2

1

If you do not use FullHttpRequest, you will get the following messages:

  • One HttpRequest message
  • Zero or more HttpContent messages
  • One LastHttpContent message

The issue with the first code snippet is that it is only accepting HttpRequest, if you want to get all the above messages, you should accept HttpObject.

I am not sure what is wrong with the second snippet, most likely you are not receiving the entire content hence FullHttpRequest is not created and emitted. I will suggest adding a LoggingHandler to the pipeline and see what you receive on the wire.

Nitesh Kant
  • 136
  • 3
0

My error was in the initializer. I did:

public class HttpRouterServerInitializer extends ChannelInitializer<SocketChannel> {
  private final HttpRouterServerHandler handler;

  public HttpRouterServerInitializer(HttpPythonModule module) {
     handler = new HttpRouterServerHandler(moduler);
  }

  public void initChannel(SocketChannel ch) {
     ch.pipeline()
        .addLast(new HttpServerCodec())
        .addLast(handler)
  }
}

where I should have done:

public class HttpRouterServerInitializer extends ChannelInitializer<SocketChannel> {
  private final HttpRouterServerHandler handler;

  public HttpRouterServerInitializer(HttpPythonModule module) {
     handler = new HttpRouterServerHandler(moduler);
  }

  public void initChannel(SocketChannel ch) {
     ch.pipeline()
        .addLast(new HttpServerCodec())
        .addLast(new HttpObjectAggregator(Integer.MAX_VALUE))
        .addLast(handler)
  }
}

The Netty documentation says about the HttpObjectAggregator class:

A ChannelHandler that aggregates an HttpMessage and its following HttpContents into a single FullHttpRequest or FullHttpResponse (depending on if it used to handle requests or responses) with no following HttpContents.

Hervé Girod
  • 465
  • 3
  • 12
  • For information I did not show this part of the code before because I did not think this was remotely connected to my problem. Turned out it was the reason of my problem :) – Hervé Girod Jul 28 '21 at 10:44