简体   繁体   English

Netty 将 HttpRequest 转换为 ByteBuf

[英]Netty convert HttpRequest to ByteBuf

In my application I need to receive a byte array on a socket, parse it as a HttpRequest to perform some check and, if the checks passes, get back to the byte array and do some more work.在我的应用程序中,我需要在套接字上接收一个字节数组,将其解析为HttpRequest以执行一些检查,如果检查通过,返回到字节数组并做一些更多的工作。

The application is based on NETTY (this is a requirement).该应用程序基于 NETTY(这是一项要求)。

My first idea was to create a pipeline like this:我的第一个想法是创建一个像这样的管道:

  1. HttpRequestDecoder (decode from ByteBuf to HttpRequest ) HttpRequestDecoder (从ByteBuf解码为HttpRequest
  2. MyHttpRequestHandler (do my own checks on the HttpRequest ) MyHttpRequestHandler (对HttpRequest进行我自己的检查)
  3. HttpRequestEncoder (encode the HttpRequest to a ByteBuf ) HttpRequestEncoder (将HttpRequest编码为ByteBuf
  4. MyButeBufHandler (do my works with the ByteBuf ) MyButeBufHandler (用ByteBuf做我的工作)

However the HttpRequestEncoder extends the ChannelOutboundHandlerAdapter so it doesn't get called for the inbound data.但是HttpRequestEncoder扩展了ChannelOutboundHandlerAdapter因此它不会被调用以获取入站数据。

How can I accomplish this task?我怎样才能完成这个任务? It would be nice to avoid decoding and re-encoding the request.避免解码和重新编码请求会很好。

Regards, Massimiliano问候, 马西米利亚诺

Use an EmbeddedChannel in MyHttpRequestHandler .MyHttpRequestHandler使用EmbeddedChannel

EmbeddedChannel ch = new EmbeddedChannel(new HttpRequestEncoder()); EmbeddedChannel ch = new EmbeddedChannel(new HttpRequestEncoder()); ch.writeOutbound(msg); ch.writeOutbound(msg); ByteBuf encoded = ch.readOutbound(); ByteBuf 编码 = ch.readOutbound();

You'll have to keep the EmbeddedChannel as a member variable of MyHttpRequestEncoder because HttpRequestEncoder is stateful.您必须将EmbeddedChannel作为MyHttpRequestEncoder的成员变量,因为HttpRequestEncoder是有状态的。 Also, please close the EmbeddedChannel when you finished using it (probably in your channelInactive() method.)另外,请在您使用完EmbeddedChannel后关闭它(可能在您的channelInactive()方法中。)

I just had to encode and decode some HttpObjects and struggled a bit with it.我只需要对一些 HttpObjects 进行编码和解码,并为此苦苦挣扎。 The hint that the decoder/encoder are stateful is very valuable.解码器/编码器有状态的提示非常有价值。

That's why I thought I'll add my findings here.这就是为什么我想我会在这里添加我的发现。 Maybe it's helpful to someone else.也许这对其他人有帮助。

I declared an RequestEncoder and a ResponseDecoder as a class member, but it still didn't work correctly.我将 RequestEncoder 和 ResponseDecoder 声明为类成员,但它仍然无法正常工作。 Until I remembered that the specific handler I was using the en/decoders within was shared...直到我记得我在其中使用 en/decoders 的特定处理程序是共享的...

That's how I got it to work in the end.这就是我最终让它工作的方式。 My sequenceNr is to distinct between the different requests.我的 sequenceNr 是为了区分不同的请求。 I create one encoder and one decoder per request and save them in a HashMap.我为每个请求创建一个编码器和一个解码器,并将它们保存在 HashMap 中。 With my sequenceNr, I'm able to always get the same decoder/encoder for the same request.使用我的序列号,我总是能够为相同的请求获得相同的解码器/编码器。 Don't forget to close and remove the de/encoder channels from the Map after processing the LastContent object.不要忘记在处理 LastContent 对象后关闭并从 Map 中移除解码器/编码器通道。

@ChannelHandler.Sharable
public class HttpTunnelingServerHandler extends ChannelDuplexHandler {
private final Map<Integer, EmbeddedChannel> decoders = Collections.synchronizedMap(new HashMap<Integer, EmbeddedChannel>());
private final Map<Integer, EmbeddedChannel> encoders = Collections.synchronizedMap(new HashMap<Integer, EmbeddedChannel>());
.
.
//Encoding
if (!encoders.containsKey(currentResponse.getSequenceNr())) {
        encoders.put(currentResponse.getSequenceNr(), new EmbeddedChannel(new HttpResponseEncoder()));
    }
    EmbeddedChannel encoderChannel = encoders.get(currentResponse.getSequenceNr());
    encoderChannel.writeOutbound(recievedHttpObject);
    ByteBuf encoded = (ByteBuf) encoderChannel.readOutbound();
.
.
//Decoding
if (!decoders.containsKey(sequenceNr)) {
        decoders.put(sequenceNr, new EmbeddedChannel(new HttpRequestDecoder()));
        }
        EmbeddedChannel decoderChannel = decoders.get(sequenceNr);
        decoderChannel.writeInbound(bb);
        HttpObject httpObject = (HttpObject) decoderChannel.readInbound();

}

How about the put the EmbeddedChannel as the handler channel's attribute, instead of HashMap.如何将 EmbeddedChannel 作为处理程序通道的属性,而不是 HashMap。 Isn't it the same what you claim to solve the stateful encoder/decoder?与您声称解决有状态编码器/解码器的方法不一样吗?

@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
      ctx.channel().attr(EMBEDED_CH).set( new EmbeddedChannel(new HttpRequestDecoder()));
      super.channelActive(ctx);
}
    
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
      EmbeddedChannel embedCh = ctx.channel().attr(EMBEDED_CH).get();
      if (embedCh != null) {
          embedCh.close();
      }

      super.channelInactive(ctx);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM