HTTP Practical Guide: Content Encoding, Transfer Encoding, and Range Requests
This article explains HTTP content encoding, transfer (chunked) encoding, and range requests, detailing their purpose, relevant headers, encoding types, and providing Java client and Netty server code examples to demonstrate how to implement and analyze these features for large file transfers.
The article concludes the "HTTP Practical" series by focusing on three HTTP features essential for large file transfers: content encoding, transfer (chunked) encoding, and range requests.
Content Encoding
Content encoding transforms the entity body to a more suitable format for transmission, indicated by the Content-Encoding header. Standard encodings include gzip , compress , deflate , and identity , as shown in the table below.
Encoding Type
Description
gzip
GNU zip compression
compress
Unix compress program
deflate
zlib format compression
identity
No encoding (default)
When a client compresses the body, it must add Content-Encoding: gzip (or another encoding) and set Content-Length to the size of the compressed data. The server must decode the data before processing.
Code Example – Client
public class ContentEncodingHttpClient {
static final CloseableHttpClient HTTP_CLIENT = HttpClientBuilder.create().build();
public static void main(String[] args) throws Exception {
HttpPost post = new HttpPost("http://127.0.0.1:8080");
post.setEntity(new GzipCompressingEntity(new StringEntity("Hi! I'm a message!")));
CloseableHttpResponse execute = HTTP_CLIENT.execute(post);
System.out.println(EntityUtils.toString(execute.getEntity()));
post.releaseConnection();
}
}The client uses Apache HttpClient’s GzipCompressingEntity to compress the payload and automatically enables chunked transfer.
Code Example – Server
public class NettyHttpServer {
public static void main(String[] args) throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.option(ChannelOption.SO_BACKLOG, 1024);
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new HttpHelloWorldServerInitializer());
Channel ch = b.bind(8080).sync().channel();
ch.closeFuture().sync();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
public class ContentEncodingServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
if (msg instanceof FullHttpRequest) {
FullHttpRequest req = (FullHttpRequest) msg;
ByteBuf content = req.content();
byte[] bytes = new byte[content.readableBytes()];
content.readBytes(bytes);
GzipDecompressingEntity gzipDecompressingEntity = new GzipDecompressingEntity(new ByteArrayEntity(bytes));
System.out.println("Encoded length: " + req.headers().get("content-length"));
System.out.print("Decoded data: ");
gzipDecompressingEntity.writeTo(System.out);
}
super.channelRead(ctx, msg);
}
}The server adds a handler that detects FullHttpRequest , extracts the compressed bytes, decompresses them with GzipDecompressingEntity , and prints the original message.
Transfer Encoding (Chunked)
Chunked transfer encoding splits the message body into a series of chunks, each preceded by its size in hexadecimal. It is enabled by the header Transfer-Encoding: chunked . The article shows a raw HTTP request example with chunked data and explains the meaning of the size line ( 12 → 18 bytes) and the terminating 0 chunk.
Chunked Request Example
POST / HTTP/1.1
Transfer-Encoding: chunked
Content-Type: text/plain; charset=ISO-8859-1
Host: 127.0.0.1:8080
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.5.13 (Java/1.8.0_311)
Accept-Encoding: gzip,deflate
12
Hi! I'm a message!
0Apache HttpClient implements chunked encoding through a series of internal methods ( DefaultBHttpClientConnection#sendRequestEntity , BHttpConnectionBase#createOutputStream , ChunkedOutputStream#write , etc.), which the article illustrates with diagrams.
Range Requests
Range requests allow clients to retrieve or upload only a portion of a large resource, using the Range request header (e.g., bytes=0-99 ) and the server’s Accept-Ranges: bytes response header. This enables resumable downloads and multi‑threaded downloading.
The server validates the requested range, responds with 206 Partial Content and a Content-Range header (e.g., bytes 0-10/100 ), then sends the requested fragment.
Typical usage steps: send a HEAD request to check support, launch N threads each with its own Range , and on interruption re‑request only the missing segment.
Conclusion
The article wraps up the essential HTTP features—content encoding, chunked transfer encoding, and range requests—providing both conceptual explanations and practical Java/Netty code to help developers handle large file transfers efficiently.
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.