private NettyBody body(Request request, boolean connect) throws IOException {
    NettyBody nettyBody = null;
    if (!connect) {

      Charset bodyCharset =
          request.getBodyCharset() == null ? DEFAULT_CHARSET : request.getBodyCharset();

      if (request.getByteData() != null) nettyBody = new NettyByteArrayBody(request.getByteData());
      else if (request.getCompositeByteData() != null)
        nettyBody = new NettyCompositeByteArrayBody(request.getCompositeByteData());
      else if (request.getStringData() != null)
        nettyBody =
            new NettyByteBufferBody(
                StringUtils.charSequence2ByteBuffer(request.getStringData(), bodyCharset));
      else if (request.getByteBufferData() != null)
        nettyBody = new NettyByteBufferBody(request.getByteBufferData());
      else if (request.getStreamData() != null)
        nettyBody = new NettyInputStreamBody(request.getStreamData(), config);
      else if (isNonEmpty(request.getFormParams())) {

        String contentType = null;
        if (!request.getHeaders().containsKey(CONTENT_TYPE))
          contentType = HttpHeaders.Values.APPLICATION_X_WWW_FORM_URLENCODED;

        nettyBody =
            new NettyByteBufferBody(
                urlEncodeFormParams(request.getFormParams(), bodyCharset), contentType);

      } else if (isNonEmpty(request.getParts()))
        nettyBody = new NettyMultipartBody(request.getParts(), request.getHeaders(), config);
      else if (request.getFile() != null) nettyBody = new NettyFileBody(request.getFile(), config);
      else if (request.getBodyGenerator() instanceof FileBodyGenerator) {
        FileBodyGenerator fileBodyGenerator = (FileBodyGenerator) request.getBodyGenerator();
        nettyBody =
            new NettyFileBody(
                fileBodyGenerator.getFile(),
                fileBodyGenerator.getRegionSeek(),
                fileBodyGenerator.getRegionLength(),
                config);

      } else if (request.getBodyGenerator() instanceof InputStreamBodyGenerator)
        nettyBody =
            new NettyInputStreamBody(
                InputStreamBodyGenerator.class.cast(request.getBodyGenerator()).getInputStream(),
                config);
      else if (request.getBodyGenerator() != null)
        nettyBody = new NettyBodyBody(request.getBodyGenerator().createBody(), config);
    }

    return nettyBody;
  }
  @SuppressWarnings("unchecked")
  public boolean sendRequest(
      final FilterChainContext ctx, final Request request, final HttpRequestPacket requestPacket)
      throws IOException {

    boolean isWriteComplete = true;

    if (Utils.requestHasEntityBody(request)) {
      final HttpTxContext context = HttpTxContext.get(ctx);
      BodyHandler handler = bodyHandlerFactory.getBodyHandler(request);
      if (requestPacket.getHeaders().contains(Header.Expect)
          && requestPacket.getHeaders().getValue(1).equalsIgnoreCase("100-Continue")) {
        // We have to set the content-length now as the headers will be flushed
        // before the FileBodyHandler is invoked.  If we don't do it here, and
        // the user didn't explicitly set the length, then the transfer-encoding
        // will be chunked and zero-copy file transfer will not occur.
        final File f = request.getFile();
        if (f != null) {
          requestPacket.setContentLengthLong(f.length());
        }
        handler = new ExpectHandler(handler);
      }
      context.setBodyHandler(handler);
      if (logger.isDebugEnabled()) {
        logger.debug("REQUEST: {}", requestPacket);
      }
      isWriteComplete = handler.doHandle(ctx, request, requestPacket);
    } else {
      HttpContent content = HttpContent.builder(requestPacket).last(true).build();
      if (logger.isDebugEnabled()) {
        logger.debug("REQUEST: {}", requestPacket);
      }
      ctx.write(content, ctx.getTransportContext().getCompletionHandler());
    }

    return isWriteComplete;
  }