v1.0.12 — HEAD resend-loop fix + upstream 7139d39
Merges winddriver 7139d39 (connection Request lifetime) and fixes the HEAD resend loop in both the HTTP server and the HTTP client.
HEAD resend loop (FIX-HEAD-LOOP-1/2, fork commit dd6d4b0). For HEAD, TCrossHttpResponse._Send (server) and TCrossHttpClientConnection._HttpSend (client) passed the header source straight to the send loop. Header sources rebuild the header on every call and never return False, and the send loop calls the source again after each completed send, so the header block was resent until the peer closed the connection.
- Server side: a keep-alive client read the extra header copies as the next response.
- Client side: the server received dozens of duplicate HEAD requests. When the client moved on, a server still handling one of them read a connection that
InternalClosehad already cleared — an intermittentEAccessViolation(read of address 0) in horse-provider-crosssocket.
HEAD now goes through the same one-shot header wrapper as other methods and stops after the header. The same bug is in upstream master; reported as winddriver#203.
Upstream 7139d39 (merge commit d7f24d8). The connection keeps the last complete request (FLastRequest under FLastRequestLock), so Connection.Request no longer changes while the next request is being parsed. No request is dispatched after InternalClose (FRequestClosed), and closing clears the request's FConnectionObj as well as FConnection. Adds FPC Net/Tests/FPC/HttpRequestLifetimeTests.
Request.Connection still becomes nil when the peer disconnects, so consumers must nil-check it. horse-provider-crosssocket does from its FIX-CONN-NIL-1 commit onward (merged in PR winddriver#15).
Validated on Windows (IOCP) with Delphi: horse-provider-crosssocket integration suite, 20 of 20 consecutive runs green against this merge (139/139 each), after the HEAD-loop crash had hit 1 to 4 runs in 10. Not run for this release: the FPC test suites, and Linux (epoll).