Backend Development 15 min read

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.

Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
HTTP Practical Guide: Content Encoding, Transfer Encoding, and Range Requests

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!
0

Apache 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.

JavaNettyHTTPChunkedContent-EncodingRange RequestsTransfer-Encoding
Rare Earth Juejin Tech Community
Written by

Rare Earth Juejin Tech Community

Juejin, a tech community that helps developers grow.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.