在 Netty 中解码 PUT 请求

decoding a PUT request in Netty

我使用以下处理程序在 Netty 中创建了一个 HTTPServer:

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);
}

我在 Python 中使用 http.client:

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

出于某种原因,我无法获取请求的 BODY(json 内容)。原因好像是我的HttpRequest不是FullHttpRequest,所以我拿不到它的content()

如果我打印我的请求内容,我有类似的东西:

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

我还尝试用我的处理程序的 FullHttpRequest 替换 HttpRequest,但在这种情况下,Netty 服务器不再响应,这导致异常 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);
}

我的错误在哪里?

如果您不使用 FullHttpRequest,您将收到以下消息:

  • 一条 HttpRequest 条消息
  • 零个或多个 HttpContent 条消息
  • 一条LastHttpContent条消息

第一个代码片段的问题是它只接受HttpRequest,如果你想得到以上所有消息,你应该接受HttpObject

我不确定第二个片段有什么问题,很可能您没有收到完整的内容,因此 FullHttpRequest 没有创建和发出。我会建议在管道中添加一个 LoggingHandler 并查看您在线上收到的内容。

我的错误是在初始化程序中。我做了:

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)
  }
}

我应该做的地方:

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)
  }
}

Netty 文档说 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.