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

@ -54,7 +54,6 @@ struct ClientHTTP1::Impl {
std::string host;
std::uint16_t port;
std::unique_ptr<ClientTCP> tcp;
std::chrono::milliseconds timeout{30000};
void Connect() {
tcp = std::make_unique<ClientTCP>(host, port);
@ -68,7 +67,8 @@ struct ClientHTTP1::Impl {
// is set as soon as any response byte arrives, which is what decides
// whether a failure is safe to replay on a new connection.
HTTPResponse Exchange(const std::string& wire, std::string_view method,
const HTTP1::MessageLimits& limits, bool& received) {
const HTTP1::MessageLimits& limits,
std::chrono::milliseconds timeout, bool& received) {
tcp->Send(wire.data(), static_cast<std::uint32_t>(wire.size()));
HTTP1::MessageParser parser(HTTP1::MessageKind::Response, limits);
@ -127,7 +127,7 @@ HTTPResponse ClientHTTP1::Send(const HTTPRequest& request) {
bool received = false;
try {
return impl->Exchange(wire, method, limits, received);
return impl->Exchange(wire, method, limits, timeout, received);
} catch (const std::exception&) {
impl->Close();
if (attempt == 0 && reused && !received) continue;