cppalliance / http_proto

HTTP/1 parsing and serialization algorithms using C++11
https://develop.http-proto.cpp.al/
Boost Software License 1.0
23 stars 10 forks source link

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

Open ashtum opened 2 months ago

ashtum commented 2 months ago

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();
vinniefalco commented 2 months ago

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

ashtum commented 2 months ago

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.