http_proto icon indicating copy to clipboard operation
http_proto copied to clipboard

`parser` should have an interface to check if it needs input

Open ashtum opened this issue 1 year ago • 2 comments

If two or more HTTP responses are read into the parser buffer, and the parser::prepare() buffer returns a non-empty mutable buffer, then the subsequent async_read_some operation on the stream will block indefinitely, assuming all responses have already been delivered. For example:

context ctx;
response_parser::config cfg;
install_parser_service(ctx, cfg);
response_parser pr(ctx);
system::error_code ec;
pr.reset();
pr.start_head_response();
std::string in = 
    "HTTP/1.1 200 OK\r\n"
    "\r\n"
    "HTTP/1.1 200 OK\r\n"
    "\r\n";
auto n = buffers::buffer_copy(
    pr.prepare(),
    buffers::const_buffer(in.data(), in.size()));
BOOST_TEST(n == in.size());
pr.commit(n);
pr.parse(ec);
BOOST_TEST(! ec.failed());
BOOST_TEST(pr.got_header());
pr.start_head_response();
BOOST_TEST(buffers::buffer_size(pr.prepare()) > 0);

This happens because the leftover data in the buffer isn't fully parsed when parser::prepare() is called. As a result, we can't determine if the buffer contains a complete or a partial message. To prevent indefinite blocking, we should assume that any leftover data after parsing a message might indicate a complete message. Therefore, we should avoid initiating another read attempt if leftovers are present.

The flow would be as follows:

pr.start();
if (pr.need_data())
{
  // Prepare buffer and read from the stream
}
pr.parse();

ashtum avatar Aug 14 '24 14:08 ashtum

You should show the smallest possible example code which uses the parser to extract two complete messages which are already stuffed into its input buffer

vinniefalco avatar Aug 14 '24 16:08 vinniefalco

You should show the smallest possible example code which uses the parser to extract two complete messages which are already stuffed into its input buffer

I've added the example to the first comment.

ashtum avatar Aug 15 '24 15:08 ashtum

The behavior has changed in a way that requires the user to call parser::parse and check for error::need_input before calling parser::prepare and performing a read.

ashtum avatar Oct 27 '25 11:10 ashtum