private void encodeChunkedContent( ChannelHandlerContext ctx, Object msg, int contentLength, List<Object> out) { if (contentLength > 0) { byte[] length = Integer.toHexString(contentLength).getBytes(CharsetUtil.US_ASCII); ByteBuf buf = ctx.alloc().buffer(length.length + 2); buf.writeBytes(length); buf.writeBytes(CRLF); out.add(buf); out.add(encodeAndRetain(msg)); out.add(CRLF_BUF.duplicate()); } if (msg instanceof LastHttpContent) { HttpHeaders headers = ((LastHttpContent) msg).trailingHeaders(); if (headers.isEmpty()) { out.add(ZERO_CRLF_CRLF_BUF.duplicate()); } else { ByteBuf buf = ctx.alloc().buffer(); buf.writeBytes(ZERO_CRLF); HttpHeaders.encode(headers, buf); buf.writeBytes(CRLF); out.add(buf); } state = ST_INIT; } else { if (contentLength == 0) { // Need to produce some output otherwise an // IllegalstateException will be thrown out.add(EMPTY_BUFFER); } } }
@Override protected void encode(ChannelHandlerContext ctx, Object msg, List<Object> out) throws Exception { ByteBuf buf = null; if (msg instanceof HttpMessage) { if (state != ST_INIT) { throw new IllegalStateException( "unexpected message type: " + StringUtil.simpleClassName(msg)); } @SuppressWarnings({"unchecked", "CastConflictsWithInstanceof"}) H m = (H) msg; buf = ctx.alloc().buffer(); // Encode the message. encodeInitialLine(buf, m); HttpHeaders.encode(m.headers(), buf); buf.writeBytes(CRLF); state = HttpHeaders.isTransferEncodingChunked(m) ? ST_CONTENT_CHUNK : ST_CONTENT_NON_CHUNK; } if (msg instanceof HttpContent || msg instanceof ByteBuf || msg instanceof FileRegion) { if (state == ST_INIT) { throw new IllegalStateException( "unexpected message type: " + StringUtil.simpleClassName(msg)); } int contentLength = contentLength(msg); if (state == ST_CONTENT_NON_CHUNK) { if (contentLength > 0) { if (buf != null && buf.writableBytes() >= contentLength && msg instanceof HttpContent) { // merge into other buffer for performance reasons buf.writeBytes(((HttpContent) msg).content()); out.add(buf); } else { if (buf != null) { out.add(buf); } out.add(encodeAndRetain(msg)); } } else { if (buf != null) { out.add(buf); } else { // Need to produce some output otherwise an // IllegalStateException will be thrown out.add(EMPTY_BUFFER); } } if (msg instanceof LastHttpContent) { state = ST_INIT; } } else if (state == ST_CONTENT_CHUNK) { if (buf != null) { out.add(buf); } encodeChunkedContent(ctx, msg, contentLength, out); } else { throw new Error(); } } else { if (buf != null) { out.add(buf); } } }