В моем приложении мне нужно получить массив байтов в сокете, проанализировать его как HttpRequest для выполнения некоторой проверки и, если проверки пройдут, вернитесь в массив байтов и выполните еще одну работу.
Приложение основано на NETTY (это требование).
Моя первая идея заключалась в создании такого конвейера:
Однако HttpRequestEncoder расширяет ChannelOutboundHandlerAdapter, чтобы он не вызывался для входящих данных.
Как я могу выполнить эту задачу? Было бы неплохо избежать декодирования и повторного кодирования запроса.
С уважением, Массимилиано
Используйте EmbeddedChannel
в MyHttpRequestHandler
.
EmbeddedChannel ch = new EmbeddedChannel (новый HttpRequestEncoder()); ch.writeOutbound(MSG); ByteBuf encoded = ch.readOutbound();
Вам нужно будет сохранить EmbeddedChannel
как переменную-член MyHttpRequestEncoder
потому что HttpRequestEncoder
имеет состояние. Также, пожалуйста, закройте EmbeddedChannel
когда вы закончите использовать его (возможно, в вашем методе channelInactive()
.)
Мне просто нужно было кодировать и декодировать некоторые HttpObjects и немного с этим бороться. Подсказка о том, что декодер/кодировщик является работоспособной, очень ценна.
Вот почему я подумал, что добавлю свои выводы здесь. Может быть, это полезно для кого-то другого.
Я объявлял RequestEncoder и ResponseDecoder как член класса, но он все еще работал неправильно. Пока я не вспомнил, что конкретный обработчик, который я использовал en/decoders внутри, был разделен...
Это то, как я получил его, чтобы работать в конце. Моя последовательностьNr должна различаться между различными запросами. Я создаю один кодировщик и один декодер для каждого запроса и сохраняю их в HashMap. С моей последовательностьюNr я могу всегда получать один и тот же декодер/кодировщик для одного и того же запроса. Не забудьте закрыть и удалить каналы de/encoder с карты после обработки объекта LastContent.
@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();
}
io.netty.handler.codec.EncoderException: java.lang.IllegalStateException: unexpected message type: LastHttpContent$1 at io.netty.handler.codec.MessageToMessageEncoder.write(MessageToMessageEncoder.java:107)