Commits
Tarun Sukhani authored 1344267846b
fix(server): terminate 304 responses so keep-alive connections survive Both 304 Not Modified fast paths -- copyResponse's File branch and serveStatic -- wrote a headers-only DefaultHttpResponse and stopped there. That was correct under Netty 3, where an HttpResponse was one complete message, but Netty 4 splits a message into HttpResponse + HttpContent* + a terminal LastHttpContent. HttpObjectEncoder is a state machine that stays in ST_CONTENT_* until it sees that terminator and refuses to encode the next response on the channel, so a single 304 wedged the encoder and every subsequent request on that keep-alive connection went unanswered. Terminate both branches with LastHttpContent.EMPTY_LAST_CONTENT, matching what the adjacent InputStream and ChunkedInput 304 branches already did. The bug is only observable across two requests on one TCP connection, so the regression test drives a raw socket: HttpClient's pooling gives no guarantee the second request reuses the first connection, and FunctionalTest.GET never reaches the Netty encoder at all. Against the unfixed handler both cases hang until the 5s socket timeout. Adds TestController.binaryFile (renderBinary sets response.direct = file) to reach the copyResponse branch, which no existing route exercised. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>