docs(http1): document the HTTP/1.1 stack, and expose the client's timeout

README: HTTP/1.1 in the intro, feature list, module list, browser-build
exclusions, dependencies and test list, plus a Components section
covering both classes, the standalone codec, what is and is not
implemented, the smuggling-shaped inputs that are rejected, and an
explicit note that this path is plaintext and belongs behind a TLS
terminator.

ClientHTTP1::timeout was hard-coded and invisible; make it a public
member alongside `limits`, mirroring the listener's timeouts.

Also pipelining coverage in ShouldSendRecieveHTTP1: two requests written
before either is answered, driven from a raw socket since ClientHTTP1
waits for each response.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
catbot 2026-07-27 01:02:37 +00:00
commit a79ab6a024
4 changed files with 102 additions and 8 deletions

View file

@ -73,6 +73,34 @@ int main() {
// Every exchange above shared one connection.
Check(listener.listener.AcceptedCount() == 1, "the whole test used a single connection");
// Pipelining: two requests written in one go, before either is
// answered. The responses must come back in order, on that same
// connection. ClientHTTP1 never does this — it waits for each
// response — so drive it from a raw socket.
{
ClientTCP socket("localhost", 8090);
const std::string pipelined =
"GET / HTTP/1.1\r\nHost: localhost\r\n\r\n"
"GET /nope HTTP/1.1\r\nHost: localhost\r\n\r\n";
socket.Send(pipelined.data(), static_cast<std::uint32_t>(pipelined.size()));
HTTP1::MessageParser parser(HTTP1::MessageKind::Response);
std::string first;
std::string second;
while (second.empty()) {
std::vector<char> chunk = socket.RecieveSync();
parser.Feed(chunk.data(), chunk.size());
while (parser.Complete()) {
HTTPResponse response = parser.TakeResponse();
(first.empty() ? first : second) = response.status;
parser.Reset();
if (!second.empty()) break;
}
}
Check(first == "200", "first pipelined response");
Check(second == "404", "second pipelined response, in order");
}
listener.Stop();
} catch (const std::exception& error) {
std::println("threw: {}", error.what());