У меня есть прокси-сервер netty, который работает и работает.Как только netty получает httpRequest, он выполняет следующие действия:
1) Метод MainHandler # channelRead создает объект FullHttpRequest, который передается другому методу.В этом методе я клонирую объект fullHttpRequest, изменяю содержимое (тело запроса), создаю клиентский bootStrap с SubHandler и делаю запрос с измененным объектом на удаленный сервер.
После завершения этой обработки я позволил исходному объекту запроса выполнитьпрокси на удаленный сервер.То, что я наблюдаю, если я закомментировал invokeAndParseClient
(который является клиентской загрузкой), прокси работает нормально.Если у меня есть invokeAndParseClient
, я получаю сообщение об ошибке (трассировка стека ниже)
ПРИМЕЧАНИЕ: исключение выдается из proxyRequest и НЕ invokeAndParseClient.
Вот действующий код
class MainHandler extends ChannelDuplexHandler {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
if (msg instanceof HttpRequest) {
FullHttpRequest request = (FullHttpRequest) msg;
invokeAndParseClient(request);
proxyRequest(ctx, request);
}
}
public void invokeAndParseClient(FullHttpRequest request) {
FullHttpRequest dup = req.duplicate();
ByteBuf content = dup.content().copy();
String newContent = modifiedContent(content); //modifies content to String, do some String replacments
ByteBuf buf = Unpooled.wrappedBuffer(newContent.getBytes(Charset.forName("UTF-8")));
dup.replace(buf); //replace content on the request
BootStrap b = new Bootstrap()
.group(bossGroup())
.channel(NioSocketChannel.class)
.handler(new RemoteChannelInitializer());
Channel ch = bootstrap.connect(remoteSocketAddress).sync().channel();
ChannelFuture f = ch.writeAndFlush(clonedReq);
//need to close channel. but have to figure out when
}
public class RemoteChannelInitializer extends ChannelInitializer<SocketChannel> {
@Override
public void initChannel(SocketChannel ch) {
ChannelPipeline p = ch.pipeline();
p.addLast(new LoggingHandler(LogLevel.INFO));
p.addLast(new HttpClientCodec());
p.addLast(new HttpObjectAggregator(1024 * 1024, true));
p.addLast(new ClientHandler()));
}
}
public class ClientHandler extends ChannelInboundHandlerAdapter {
private static final Logger LOGGER = LoggerFactory.getLogger(ClientRequestHandler.class);
@Override
public void channelRead(final ChannelHandlerContext ctx, Object msg) {
LOGGER.info("here you gooooo");
if (msg instanceof FullHttpResponse) {
LOGGER.info("this is fullHttpResponse");
FullHttpResponse full = (FullHttpResponse) msg;
FullHttpResponse dup = full.copy();
LOGGER.info("response code ===> " + full.status());
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
}
С этим кодом я получаю следующее исключение.но как только я закомментирую invokeAndParseClient (запрос), он работает нормально.в чем здесь проблема?
2019-05-21 16:08:59.524 WARN 45091 --- [tLoopGroup-3-25] io.netty.channel.ChannelOutboundBuffer : Failed to mark a promise as success because it has failed already: DefaultChannelPromise@2e4d789f(failure: io.netty.handler.codec.EncoderException: io.netty.util.IllegalReferenceCountException: refCnt: 0, decrement: 1), unnotified cause:
io.netty.handler.codec.EncoderException: io.netty.util.IllegalReferenceCountException: refCnt: 0, decrement: 1
at io.netty.handler.codec.MessageToMessageEncoder.write(MessageToMessageEncoder.java:106) ~[netty-codec-4.1.31.Final.jar:4.1.31.Final]
at io.netty.channel.CombinedChannelDuplexHandler.write(CombinedChannelDuplexHandler.java:348) ~[netty-transport-4.1.31.Final.jar:4.1.31.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeWrite0(AbstractChannelHandlerContext.java:738) ~[netty-transport-4.1.31.Final.jar:4.1.31.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeWriteAndFlush(AbstractChannelHandlerContext.java:801) ~[netty-transport-4.1.31.Final.jar:4.1.31.Final]
at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:814) ~[netty-transport-4.1.31.Final.jar:4.1.31.Final]
at io.netty.channel.AbstractChannelHandlerContext.writeAndFlush(AbstractChannelHandlerContext.java:794) ~[netty-transport-4.1.31.Final.jar:4.1.31.Final]
at io.netty.channel.AbstractChannelHandlerContext.writeAndFlush(AbstractChannelHandlerContext.java:837) ~[netty-transport-4.1.31.Final.jar:4.1.31.Final]
at io.netty.channel.DefaultChannelPipeline.writeAndFlush(DefaultChannelPipeline.java:1071) ~[netty-transport-4.1.31.Final.jar:4.1.31.Final]
at io.netty.channel.AbstractChannel.writeAndFlush(AbstractChannel.java:300) ~[netty-transport-4.1.31.Final.jar:4.1.31.Final]
at com.example.MainHandler.proxyRequest(ClientRequestHandler.java:178) ~[classes/:na]