From 1d24e78930ff24c8f260cf77686be98fbd2f9e55 Mon Sep 17 00:00:00 2001 From: Mohammad Nejati Date: Mon, 27 Oct 2025 07:56:51 +0000 Subject: [PATCH 1/3] http_proto::method document guarantees about its values Closes #179 --- include/boost/http_proto/method.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/boost/http_proto/method.hpp b/include/boost/http_proto/method.hpp index 399a2e3e..472b57f5 100644 --- a/include/boost/http_proto/method.hpp +++ b/include/boost/http_proto/method.hpp @@ -21,6 +21,9 @@ namespace http_proto { Each item corresponds to a particular method string used in HTTP request messages. + + @note The values are guaranteed to be consecutive, + starting at 0. */ enum class method : char { From 5c91ededb66167afdf0b639d2204476f69a62054 Mon Sep 17 00:00:00 2001 From: Mohammad Nejati Date: Mon, 27 Oct 2025 08:28:08 +0000 Subject: [PATCH 2/3] serializer javadocs uses 'writing' instead of 'reading' Closes #176 --- include/boost/http_proto/serializer.hpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/include/boost/http_proto/serializer.hpp b/include/boost/http_proto/serializer.hpp index 8f3b8f22..b28771c0 100644 --- a/include/boost/http_proto/serializer.hpp +++ b/include/boost/http_proto/serializer.hpp @@ -332,15 +332,15 @@ class serializer Initializes the serializer with the HTTP start-line and headers from `m`, and returns - a @ref stream object for reading the body - from an external source. + a @ref stream object for writing the body + data into the serializer's internal buffer. Once the serializer is destroyed, @ref reset is called, or @ref is_done returns true, the only valid operation on the stream is destruction. The stream allows inverted control flow: the - caller supplies body data via the serializer’s + caller supplies body data to the serializer’s internal buffer while reading from an external source. @@ -351,17 +351,17 @@ class serializer @par Example @code - serializer::stream strm = serializer.start_stream(response); + serializer::stream st = serializer.start_stream(response); do { - if(strm.is_open()) + if(st.is_open()) { - std::size_t n = source.read_some(strm.prepare()); + std::size_t n = source.read_some(st.prepare()); if(ec == error::eof) - strm.close(); + st.close(); else - strm.commit(n); + st.commit(n); } write_some(client, serializer); @@ -392,8 +392,8 @@ class serializer @param m The message to read the HTTP start-line and headers from. - @return A @ref stream object for reading body - content into the serializer's buffer. + @return A @ref stream object for writing the body + data into the serializer's internal buffer. @see @ref stream, From 2df93f1e201aca1abf7054a2d26a4a00e71681b2 Mon Sep 17 00:00:00 2001 From: Mohammad Nejati Date: Mon, 27 Oct 2025 10:16:32 +0000 Subject: [PATCH 3/3] refactor fields_base operator<< Fixes #182 --- include/boost/http_proto/fields_base.hpp | 76 +++++++++++++----------- src/fields_base.cpp | 10 +++- test/unit/fields_base.cpp | 12 ++-- 3 files changed, 55 insertions(+), 43 deletions(-) diff --git a/include/boost/http_proto/fields_base.hpp b/include/boost/http_proto/fields_base.hpp index e9c4e4bc..01b96f04 100644 --- a/include/boost/http_proto/fields_base.hpp +++ b/include/boost/http_proto/fields_base.hpp @@ -1303,6 +1303,46 @@ class fields_base core::string_view value, system::error_code& ec); + //-------------------------------------------- + + /** Format the container to the output stream + + This function serializes the container to + the specified output stream. + + @par Example + @code + request req; + req.set(field::content_length, "42"); + std::stringstream ss; + ss << req; + assert( ss.str() == "GET / HTTP/1.1\nContent-Length: 42\n" ); + @endcode + + @par Effects + @code + return os << f.buffer(); + @endcode + + @par Complexity + Linear in `f.buffer().size()` + + @par Exception Safety + Basic guarantee. + + @return A reference to the output stream, for chaining + + @param os The output stream to write to. + + @param f The container to write. + */ + friend + BOOST_HTTP_PROTO_DECL + std::ostream& + operator<<( + std::ostream& os, + const fields_base& f); + private: BOOST_HTTP_PROTO_DECL void @@ -1352,42 +1392,6 @@ class fields_base std::size_t i) const noexcept; }; -/** Format the container to the output stream - - This function serializes the container to - the specified output stream. - - @par Example - @code - request req; - std::stringstream ss; - ss << req; - assert( ss.str() == "GET / HTTP/1.1\r\n\r\n" ); - @endcode - - @par Effects - @code - return os << f.buffer(); - @endcode - - @par Complexity - Linear in `f.buffer().size()` - - @par Exception Safety - Basic guarantee. - - @return A reference to the output stream, for chaining - - @param os The output stream to write to. - - @param f The container to write. -*/ -BOOST_HTTP_PROTO_DECL -std::ostream& -operator<<( - std::ostream& os, - const fields_base& f); - } // http_proto } // boost diff --git a/src/fields_base.cpp b/src/fields_base.cpp index a58e4a81..ba62e591 100644 --- a/src/fields_base.cpp +++ b/src/fields_base.cpp @@ -850,14 +850,18 @@ find_all( &h_, find(name).i_); } -//------------------------------------------------ - std::ostream& operator<<( std::ostream& os, const fields_base& f) { - return os << f.buffer(); + if(f.h_.prefix != 0) + os << core::string_view(f.h_.cbuf, f.h_.prefix - 2) << '\n'; + + for(auto ref : f) + os << ref.name << ": " << ref.value << '\n'; + + return os; } //------------------------------------------------ diff --git a/test/unit/fields_base.cpp b/test/unit/fields_base.cpp index 3bce305c..88300987 100644 --- a/test/unit/fields_base.cpp +++ b/test/unit/fields_base.cpp @@ -1704,11 +1704,15 @@ struct fields_base_test // operator<< { std::stringstream ss; - fields f; - f.set(field::content_length, "42"); - ss << f; + response r; + r.set(field::content_length, "42"); + r.set(field::connection, "Close"); + ss << r; BOOST_TEST_EQ( - ss.str(), "Content-Length: 42\r\n\r\n"); + ss.str(), + "HTTP/1.1 200 OK\n" + "Content-Length: 42\n" + "Connection: Close\n"); } }