CodeRigor

LESSON

Bound response reads and always close them

Pass explicit blocking-operation timeouts, cap accepted body bytes and close resources on success or failure.

Network code owns a resource, not just a returned value. A socket-backed response must close after success, oversized input, decoding failure or cancellation. Put the read inside a context manager so ownership is visible.

Hosted exercises use a supplied transport callable that returns a fake response with status, getheaders(), read(n) and context-manager methods. The downloadable adapter uses a real HTTP connection to the local fixture server. Both satisfy the same boundary.

Acquire → bounded read → release
start / 3
The response context owns cleanup. Read one detection byte beyond the accepted body limit, then validate before returning.
Acquire → bounded read → release
The response context owns cleanup. Read one detection byte beyond the accepted body limit, then validate before returning.

Reading everything and checking its length afterward does not bound the read. Reading exactly the limit can silently hide truncation. Request limit + 1, then accept only lengths at most limit. The returned bytes remain undecoded until the next lesson.

The supplied wrapper validates finite positive timeouts and integer byte limits before effects. A Boolean is not accepted as an integer limit even though bool subclasses int in Python.

Python
limit = 4
for body in [b"", b"abcd", b"abcde", b"abcdefgh"]:
    probe = body[:limit+1]
    print("read", len(probe), "accepted", len(probe) <= limit)

Be precise about time. Our timeout is passed to supported blocking socket operations. It is not an overall wall-clock deadline: several operations or repeated trickling reads can take longer. The later retry wait budget bounds deliberate sleeps, not all network runtime. These are separate limits.

The accepted body cap also does not independently prove peak process memory; the transport and parser have allocations of their own. In this small lab, the standard HTTP parser and a bounded read keep the teaching boundary practical without claiming a universal network hardening layer.

The wrapper maps timeout and transport errors to fixed ClientError codes instead of copying raw exception messages or headers into output. Tests inspect exact read size, timeout forwarding and cleanup effects, which catch bugs that a returned-value-only test would miss.

A failure still releases ownership
start / 3
Oversize, read errors and success all leave the same context. No exit bypasses response cleanup.
A failure still releases ownership
Oversize, read errors and success all leave the same context. No exit bypasses response cleanup.
Python
closed=[]
class Response:
    def __enter__(self): return self
    def __exit__(self,*args): closed.append(True)
try:
    with Response():
        raise ValueError("oversize")
except ValueError:
    print("error handled")
print("closed", closed)

Implement the bounded read. Test an exact-limit body, a one-byte overflow, an empty body, a non-byte fake and an exception during reading. Every acquired response must close.

Next we decide whether these bounded bytes are the successful JSON page the application actually requested.

Watch & read

Free lectures, talks and readings that cover this skill from another angle. All resources →

Optional HTTP background using Requests. Our original lab uses the standard library and an injected transport; no Requests dependency is required.