title: Netty async write response and large data unknown with size
body: <p>I develop a netty http server, but when I write the response in the method ChannelInboundHandlerAdapter.channelRead0, my response result comes from another server and the size of the result is unknown, so its http response headers maybe has content-length or chunked. so I use a buffer, if it's enough (read up full data) regardless of content-length or chunked, I use content-length, otherwise I use chunked.</p>
  
  <ol>
  <li><p>How I hold the write channel of first connection then pass it to the seconde Handler inorder to write the response. ( I just directly pass ctx to write but nothing returns)</p></li>
  <li><p>How I conditionally decide write chunked data to channel or normal data with content-length (it seems not to work to add ChunkWriteHandler if chunk is needed when channelRead0.</p></li>
  </ol>
  
  <p>take a simple code for example:</p>
  
  <p>```java</p>
  
  <pre><code>EventLoopGroup bossGroup = new NioEventLoopGroup();
      final EventLoopGroup workerGroup = new NioEventLoopGroup();
  
      try {
          ServerBootstrap serverBootstrap = new ServerBootstrap();
  
          serverBootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
              .handler(new LoggingHandler(LogLevel.INFO))
              .childHandler(new ChannelInitializer&lt;Channel&gt;(){
  
                  @Override
                  protected void initChannel(Channel ch) throws Exception
                  {
                      System.out.println("Start, I accept client");
                      ChannelPipeline pipeline = ch.pipeline();
  
                      // Uncomment the following line if you want HTTPS
                      // SSLEngine engine =
                      // SecureChatSslContextFactory.getServerContext().createSSLEngine();
                      // engine.setUseClientMode(false);
                      // pipeline.addLast("ssl", new SslHandler(engine));
  
                      pipeline.addLast("decoder", new HttpRequestDecoder());
                      // Uncomment the following line if you don't want to handle HttpChunks.
                      // pipeline.addLast("aggregator", new HttpChunkAggregator(1048576));
                      pipeline.addLast("encoder", new HttpResponseEncoder());
                      // Remove the following line if you don't want automatic content
                      // compression.
                      //pipeline.addLast("aggregator", new HttpChunkAggregator(1048576));
                      pipeline.addLast("chunkedWriter", new ChunkedWriteHandler());
                      pipeline.addLast("deflater", new HttpContentCompressor());
                      pipeline.addLast("handler", new SimpleChannelInboundHandler&lt;HttpObject&gt;(){
  
                              @Override
                              protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception
                              {
                                  System.out.println("msg=" + msg);
  
                                  final ChannelHandlerContext ctxClient2Me = ctx;
  
                                  // TODO: Implement this method
                                  Bootstrap bs = new Bootstrap();
                                  try{
                                  //bs.resolver(new DnsAddressResolverGroup(NioDatagramChannel.class,  DefaultDnsServerAddressStreamProvider.INSTANCE));
                                  //.option(ChannelOption.TCP_NODELAY, java.lang.Boolean.TRUE)
                                  bs.resolver(DefaultAddressResolverGroup.INSTANCE);
                                  }catch(Exception e){
                                      e.printStackTrace();
                                  }
  
                                  bs.channel(NioSocketChannel.class);
                                  EventLoopGroup cg = workerGroup;//new NioEventLoopGroup();
                                  bs.group(cg).handler(new ChannelInitializer&lt;Channel&gt;(){
  
                                          @Override
                                          protected void initChannel(Channel ch) throws Exception
                                          {
                                              System.out.println("start, server accept me");
                                              // TODO: Implement this method
                                              ch.pipeline().addLast("http-request-encode", new HttpRequestEncoder());
                                              ch.pipeline().addLast(new HttpResponseDecoder());
                                              ch.pipeline().addLast("http-res", new SimpleChannelInboundHandler&lt;HttpObject&gt;(){
  
                                                      @Override
                                                      protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception
                                                      {
                                                          // TODO: Implement this method
                                                          System.out.println("target = " + msg);
                                                          //
                                                          if(msg instanceof HttpResponse){
                                                              HttpResponse res = (HttpResponse) msg;
                                                              HttpUtil.isTransferEncodingChunked(res);
                                                              DefaultHttpResponse resClient2Me = new DefaultHttpResponse(HttpVersion.HTTP_1_1, res.getStatus());
  
                                                              //resClient2Me.headers().set(HttpHeaderNames.TRANSFER_ENCODING, HttpHeaderValues.CHUNKED);
                                                              //resClient2Me.headers().set(HttpHeaderNames.CONTENT_LENGTH, "");
  
                                                              ctxClient2Me.write(resClient2Me);
                                                          }
                                                          if(msg instanceof LastHttpContent){
                                                              // now response the request of the client, it wastes x seconds from receiving request to response
                                                              ctxClient2Me.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT).addListener(ChannelFutureListener.CLOSE);
                                                              ctx.close();
                                                          }else if( msg instanceof HttpContent){
                                                              //ctxClient2Me.write(new DefaultHttpContent(msg)); write chunk by chunk ?
                                                          }
                                                      }
  
  
                                                  });
  
                                              System.out.println("end, server accept me");
  
                                          }
  
                                  });
  
                                  final URI uri = new URI("http://example.com/");
                                  String host = uri.getHost();
                                  ChannelFuture connectFuture= bs.connect(host, 80);
  
                                  System.out.println("to connect me to server");
  
                                  connectFuture.addListener(new ChannelFutureListener(){
  
                                          @Override
                                          public void operationComplete(ChannelFuture cf) throws Exception
                                          {
                                          }
  
                                  });
  
  
                                  ChannelFuture connetedFuture = connectFuture.sync(); // TODO optimize, wait io 
                                  System.out.println("connected me to server");
  
                                  DefaultFullHttpRequest req = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, uri.getRawPath());
                                  //req.headers().set(HttpHeaderNames.HOST, "");
                                  connetedFuture.channel().writeAndFlush(req);
  
                                  System.out.println("end of Client2Me channelRead0");
                                  System.out.println("For the seponse of Me2Server, see SimpleChannelInboundHandler.channelRead0");
                              }
  
                      });
                      System.out.println("end, I accept client");
                  }
  
              });
  
              System.out.println("========");
  
          ChannelFuture channelFuture = serverBootstrap.bind(2080).sync();
          channelFuture.channel().closeFuture().sync();
      } finally {
          bossGroup.shutdownGracefully();
          workerGroup.shutdownGracefully();
      }
  </code></pre>
  
  <p>```</p>