Add state to HTTPRequest to avoid duplicate work over I/O cycles

This commit is contained in:
Matthew Zipkin
2026-07-14 15:52:37 -04:00
parent 507e528e84
commit 90676e24ad
4 changed files with 220 additions and 137 deletions

View File

@@ -121,6 +121,9 @@ private:
* https://httpwg.org/specs/rfc9110.html#rfc.section.5.2
*/
std::vector<std::pair<std::string, std::string>> m_headers;
//! Track total bytes consumed in Read() for limit checks
size_t m_consumed{0};
};
struct HTTPVersion {
@@ -196,6 +199,27 @@ public:
std::pair<bool, std::string> GetHeader(std::string_view hdr) const;
std::string ReadBody() const { return m_body; }
void WriteHeader(std::string&& hdr, std::string&& value);
enum class State {
Init,
NeedsHeaders,
NeedsBody,
Complete,
Error
};
State GetState() const { return m_state; }
void SetState(State state) { m_state = state; }
// If a large request is sent with "Transfer-encoding: chunked" we may
// read the chunk size in a separate I/O loop iteration than the chunk
// of data itself. Store the chunk size value here until the chunk is read.
std::optional<uint64_t> m_chunk_size;
// We may also read a large chunk over multiple loop iterations.
// Track the progress of the chunk here.
uint64_t m_chunk_read{0};
private:
State m_state = State::Init;
};
class HTTPServer
@@ -563,10 +587,11 @@ public:
/**
* Try to read an HTTP request from the receive buffer.
* Updates HTTPRequest.m_state and drains buffer on error.
* @param[in] req A HTTPRequest to read into
* @returns true upon reading a complete request, otherwise false (may throw).
* @throws std::runtime_error if request is unreadable or violates protocol
*/
bool ReadRequest(HTTPRequest& req);
void ReadRequest(HTTPRequest& req);
/**
* Push data (if there is any) from client's m_send_buffer to the connected socket.