BodyHandlers.ofInputStream exposes the response body as an InputStream. The application owns that stream and must consume or close it; otherwise an HTTP connection may remain occupied.
Java streaming HTTP bodies: close the stream and cap retained bytes
Operational contract
A streaming handler avoids immediately materializing the whole body, but it does not impose a size limit by itself. This decoder reads one byte beyond an application cap and rejects overflow. try-with-resources closes the stream on either path. Closing early may prevent connection reuse, which is an acceptable cost for a rejected oversized payload. This is a cap on bytes delivered to the application after any HTTP representation handling, not a claim about wire bytes or compressed expansion. A structured parser should run only after the cap and content-type checks.
Failure case
An inventory response is expected to fit within 47,000 bytes. If the peer sends 47,001 bytes, the parser never receives a truncated record and the request fails. The caller can record response status and content type separately. It must not call the 47,000-byte prefix a complete inventory.
Java code
import java.io.IOException;
import java.io.InputStream;
import java.net.http.HttpResponse;
public class InventoryBodyReader {
public static byte[] read(HttpResponse<InputStream> response) throws IOException {
if (response.statusCode() != 200) {
try (InputStream discarded = response.body()) {
throw new IOException("Unexpected inventory status: " + response.statusCode());
}
}
try (InputStream body = response.body()) {
byte[] bytes = body.readNBytes(47_001);
if (bytes.length > 47_000) throw new IOException("Inventory body exceeds cap");
return bytes;
}
}
}Performance and ownership cost
Reading a response of N bytes below the cap is O(N) time and O(N) retained memory. The one-byte probe makes overflow detection exact at the application boundary. An early close can sacrifice pool reuse; an unbounded read risks process memory instead.
Common Mistakes
- Do not forget to close the response InputStream.
- Do not treat a capped prefix as a complete document.
- Do not rely on Content-Length alone as a verified body-size limit.
Connected lessons
- Java HttpClient: request policy, deadlines, and response size
- Java bounded line reader: reject oversized records without buffering the file
- Java cancellation: timed waits and cooperative interruption
- Java HTTP query values: encode data without changing URI structure
- Java HttpClient redirects: check the next origin before resending
- Java HttpClient deadlines: separate connection and request timeouts
- Java Retry-After: parse a bounded server delay without inventing a retry
- Java HttpClient cookies: make session storage an owned policy
- Java HTTP and fork/join decisions quiz
- Advanced Java
