diff --git a/include/boost/http/parser.hpp b/include/boost/http/parser.hpp index 321c2ab9..c728b329 100644 --- a/include/boost/http/parser.hpp +++ b/include/boost/http/parser.hpp @@ -17,7 +17,7 @@ #include #include -#include +#include #include #include #include @@ -604,7 +604,7 @@ read(Stream& stream, MB buffers) co_return {{}, 0}; std::size_t total = 0; - auto dest = capy::buffer_slice(buffers); + capy::consuming_buffers dest(buffers); for(;;) { @@ -619,7 +619,7 @@ read(Stream& stream, MB buffers) std::size_t copied = capy::buffer_copy(dest.data(), body_data); consume_body(copied); total += copied; - dest.remove_prefix(copied); + dest.consume(copied); if(capy::buffer_empty(dest.data())) co_return {{}, total}; diff --git a/test/unit/parser.cpp b/test/unit/parser.cpp index af7c3f74..169cf8d5 100644 --- a/test/unit/parser.cpp +++ b/test/unit/parser.cpp @@ -23,6 +23,7 @@ #include "test_helpers.hpp" +#include #include //------------------------------------------------ @@ -2223,6 +2224,46 @@ struct parser_coro_test BOOST_TEST(r.success); } + // Read the body into a caller-provided MutableBufferSequence. + // Exercises the parser::read(Stream&, MB) overload so it is + // actually instantiated: it is otherwise never called with a + // real buffer sequence, which let a capy buffer-API break slip + // past the build undetected. + void + testReadBuffers() + { + capy::test::fuse f; + auto r = f.armed([&](capy::test::fuse&) -> capy::task<> + { + capy::test::read_stream rs(f, 1); + rs.provide( + "HTTP/1.1 200 OK\r\n" + "Content-Length: 13\r\n" + "\r\n" + "Hello, World!"); + + response_parser pr(res_cfg_); + pr.reset(); + pr.start(); + + char storage[64]; + std::array bufs{{ + capy::mutable_buffer(storage, sizeof(storage)) }}; + auto [ec, n] = co_await pr.read(rs, bufs); + ignore_unused(ec); + + // The fuse re-runs this coroutine injecting a fault at + // each suspension point; only assert on the run that + // reads the whole body. + if(! pr.is_complete()) + co_return; + + BOOST_TEST_EQ(n, 13u); + BOOST_TEST(core::string_view(storage, n) == "Hello, World!"); + }); + BOOST_TEST(r.success); + } + void testReadChunked() { @@ -2310,6 +2351,7 @@ struct parser_coro_test testSourceForLargeBody(); testSourceForBodyTooLarge(); testRead(); + testReadBuffers(); testReadChunked(); testReadEof(); testReadOverflow();