diff --git a/CHANGELOG.md b/CHANGELOG.md index 716415f8..2a21492d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,16 @@ +Version 68: + +API Changes: + +* Change BodyReader, BodyWriter requirements + +Actions Required: + +* Change user defined instances of BodyReader and BodyWriter + to meet the new requirements. + +-------------------------------------------------------------------------------- + Version 67: * Fix doc example link diff --git a/doc/concept/BodyReader.qbk b/doc/concept/BodyReader.qbk index 817743db..f1ee27f8 100644 --- a/doc/concept/BodyReader.qbk +++ b/doc/concept/BodyReader.qbk @@ -62,17 +62,11 @@ In this table: the HTTP header. ] ][ - [`X(m);`] + [`X(m,ec);`] [] [ Constructible from `m`. The lifetime of `m` is guaranteed to end no earlier than after the `X` is destroyed. - ] -][ - [`a.init(ec)`] - [] - [ - Called immediately after construction. The function will ensure that `!ec` is `true` if there was no error or set to the appropriate error code if there was one. ] @@ -93,15 +87,6 @@ In this table: The function will ensure that `!ec` is `true` if there was no error or set to the appropriate error code if there was one. ] -][ - [`a.finish(ec)`] - [] - [ - This function is called after the reader indicates there - are no more buffers remaining. - The function will ensure that `!ec` is `true` if there was - no error or set to the appropriate error code if there was one. - ] ][ [`is_body_reader`] [`std::true_type`] diff --git a/doc/concept/BodyWriter.qbk b/doc/concept/BodyWriter.qbk index 9091d1ff..8ad355ed 100644 --- a/doc/concept/BodyWriter.qbk +++ b/doc/concept/BodyWriter.qbk @@ -29,35 +29,29 @@ In this table: * `a` denotes a value of type `X`. -* `length` is a value of type `boost::optional`. - * `b` is an object whose type meets the requirements of __ConstBufferSequence__ * `m` denotes a value of type `message&` where `std::is_same::value == true`. +* `n` is a value of type `boost::optional`. + * `ec` is a value of type [link beast.ref.beast__error_code `error_code&`]. [table Writer requirements [[expression] [type] [semantics, pre/post-conditions]] [ - [`X(m);`] + [`X(m,n,ec);`] [] [ Constructible from `m`. The lifetime of `m` is guaranteed to end no earlier than after the `X` is destroyed. The constructor - will be called the complete header is stored in `m`, and before + will be called after a complete header is stored in `m`, and before parsing body octets for messages indicating that a body is present. - ] -][ - [`a.init(length,ec)`] - [] - [ - This function is called after construction and before any body - octets are presented to the writer. The value of `length` will - be set to the content length of the body if known, otherwise - `length` will be equal to `boost::none`. Implementations of - [*BodyWriter] may use this information to optimize allocation. + The value of `n` will be set to the content length of the + body if known, otherwise `n` will be equal to `boost::none`. + Implementations of [*BodyWriter] may use this information to + optimize allocation. The function will ensure that `!ec` is `true` if there was no error or set to the appropriate error code if there was one. ] diff --git a/example/common/file_body.hpp b/example/common/file_body.hpp index a75386ff..f643061d 100644 --- a/example/common/file_body.hpp +++ b/example/common/file_body.hpp @@ -119,17 +119,12 @@ public: // always have the `file_body` as the body type. // template - reader(beast::http::message const& m); + reader(beast::http::message const& m, + beast::error_code& ec); // Destructor ~reader(); - // This function is called once before serialization - // of the body is started. - // - void - init(beast::error_code& ec); - // This function is called zero or more times to // retrieve buffers. A return value of `boost::none` // means there are no more buffers. Otherwise, @@ -138,15 +133,6 @@ public: // or not there may be additional buffers. boost::optional> get(beast::error_code& ec); - - // This function is called when reading is complete. - // It is an opportunity to perform any final actions - // which might fail, in order to return an error code. - // Operations that might fail should not be attemped in - // destructors, since an exception thrown from there - // would terminate the program. - void - finish(beast::error_code& ec); }; //] @@ -159,20 +145,9 @@ public: // template file_body::reader:: -reader(beast::http::message const& m) +reader(beast::http::message const& m, + beast::error_code& ec) : path_(m.body) -{ -} - -// This gets called right after construction, and provides -// the opportunity to return an error code. The error code -// will be propagated to the serializer and eventually -// returned to the caller. -// -inline -void -file_body::reader:: -init(beast::error_code& ec) { // Attempt to open the file for reading file_ = fopen(path_.string().c_str(), "rb"); @@ -185,9 +160,11 @@ init(beast::error_code& ec) return; } + // This is required by the error_code specification + ec = {}; + // The file was opened successfully, get the size // of the file to know how much we need to read. - ec = {}; remain_ = boost::filesystem::file_size(path_); } @@ -248,17 +225,6 @@ get(beast::error_code& ec) -> }}; } -// Called after reading is done when there's no error. -inline -void -file_body::reader:: -finish(beast::error_code& ec) -{ - // Functions which pass back errors are - // responsible for clearing the error code. - ec = {}; -} - // The destructor is always invoked if construction succeeds. // inline @@ -291,13 +257,9 @@ public: // template explicit - writer(beast::http::message& m); - - // This function is called once before parsing - // of the body is started. - // - void - init(boost::optional const& content_length, beast::error_code& ec); + writer(beast::http::message& m, + boost::optional const& content_length, + beast::error_code& ec); // This function is called one or more times to store // buffer sequences corresponding to the incoming body. @@ -330,21 +292,10 @@ public: // Just stash a reference to the path so we can open the file later. template file_body::writer:: -writer(beast::http::message& m) +writer(beast::http::message& m, + boost::optional const& content_length, + beast::error_code& ec) : path_(m.body) -{ -} - -// This gets called once when we know there's a body. -// If the content_length is set, it lets us know the exact size -// of the body. An implementation could use this to optimize its -// storage strategy. For example by attempting to reserve space -// ahead of time. -// -inline -void -file_body::writer:: -init(boost::optional const& content_length, beast::error_code& ec) { boost::ignore_unused(content_length); @@ -359,7 +310,7 @@ init(boost::optional const& content_length, beast::error_code& ec return; } - // Indicate success + // This is required by the error_code specification ec = {}; } diff --git a/include/beast/http/buffer_body.hpp b/include/beast/http/buffer_body.hpp index 485e87df..139f5b50 100644 --- a/include/beast/http/buffer_body.hpp +++ b/include/beast/http/buffer_body.hpp @@ -104,13 +104,8 @@ struct buffer_body template explicit reader(message const& msg) + Fields> const& msg, error_code& ec) : body_(msg.body) - { - } - - void - init(error_code& ec) { ec.assign(0, ec.category()); } @@ -145,12 +140,6 @@ struct buffer_body ec.assign(0, ec.category()); return boost::none; } - - void - finish(error_code& ec) - { - ec.assign(0, ec.category()); - } }; #endif @@ -165,13 +154,10 @@ struct buffer_body public: template explicit - writer(message& m) + writer(message& m, + boost::optional const&, + error_code& ec) : body_(m.body) - { - } - - void - init(boost::optional, error_code& ec) { ec.assign(0, ec.category()); } diff --git a/include/beast/http/dynamic_body.hpp b/include/beast/http/dynamic_body.hpp index eb4d7586..501b5cd7 100644 --- a/include/beast/http/dynamic_body.hpp +++ b/include/beast/http/dynamic_body.hpp @@ -52,14 +52,9 @@ struct basic_dynamic_body template explicit - reader(message< - isRequest, basic_dynamic_body, Fields> const& m) + reader(message const& m, error_code& ec) : body_(m.body) - { - } - - void - init(error_code& ec) { ec.assign(0, ec.category()); } @@ -70,12 +65,6 @@ struct basic_dynamic_body ec.assign(0, ec.category()); return {{body_.data(), false}}; } - - void - finish(error_code& ec) - { - ec.assign(0, ec.category()); - } }; #endif @@ -90,15 +79,10 @@ struct basic_dynamic_body public: template explicit - writer(message& msg) + writer(message& msg, + boost::optional const&, + error_code& ec) : body_(msg.body) - { - } - - void - init(boost::optional< - std::uint64_t> const&, error_code& ec) { ec.assign(0, ec.category()); } diff --git a/include/beast/http/empty_body.hpp b/include/beast/http/empty_body.hpp index 9aa1b118..35632ac9 100644 --- a/include/beast/http/empty_body.hpp +++ b/include/beast/http/empty_body.hpp @@ -56,13 +56,8 @@ struct empty_body template explicit - reader(message< - isRequest, empty_body, Fields> const&) - { - } - - void - init(error_code& ec) + reader(message const&, error_code& ec) { ec.assign(0, ec.category()); } @@ -73,12 +68,6 @@ struct empty_body ec.assign(0, ec.category()); return boost::none; } - - void - finish(error_code& ec) - { - ec.assign(0, ec.category()); - } }; #endif @@ -90,13 +79,9 @@ struct empty_body { template explicit - writer(message&) - { - } - - void - init(boost::optional const&, - error_code& ec) + writer(message&, + boost::optional const&, + error_code& ec) { ec.assign(0, ec.category()); } diff --git a/include/beast/http/impl/serializer.ipp b/include/beast/http/impl/serializer.ipp index 22299a90..7094537a 100644 --- a/include/beast/http/impl/serializer.ipp +++ b/include/beast/http/impl/serializer.ipp @@ -70,8 +70,7 @@ get(error_code& ec, Visit&& visit) { if(split_) goto go_header_only; - rd_.emplace(m_); - rd_->init(ec); + rd_.emplace(m_, ec); if(ec) return; auto result = rd_->get(ec); @@ -105,8 +104,7 @@ get(error_code& ec, Visit&& visit) case do_body: BOOST_ASSERT(! rd_); - rd_.emplace(m_); - rd_->init(ec); + rd_.emplace(m_, ec); if(ec) return; s_ = do_body + 1; @@ -137,8 +135,7 @@ get(error_code& ec, Visit&& visit) { if(split_) goto go_header_only_c; - rd_.emplace(m_); - rd_->init(ec); + rd_.emplace(m_, ec); if(ec) return; auto result = rd_->get(ec); @@ -183,8 +180,7 @@ get(error_code& ec, Visit&& visit) case do_body_c: BOOST_ASSERT(! rd_); - rd_.emplace(m_); - rd_->init(ec); + rd_.emplace(m_, ec); if(ec) return; s_ = do_body_c + 1; @@ -249,10 +245,6 @@ get(error_code& ec, Visit&& visit) break; go_complete: - if(rd_) - rd_->finish(ec); - if(ec) - return; s_ = do_complete; break; } diff --git a/include/beast/http/parser.hpp b/include/beast/http/parser.hpp index 132046d8..4c35e746 100644 --- a/include/beast/http/parser.hpp +++ b/include/beast/http/parser.hpp @@ -258,8 +258,7 @@ private: std::uint64_t> const& content_length, error_code& ec) { - wr_.emplace(m_); - wr_->init(content_length, ec); + wr_.emplace(m_, content_length, ec); } void diff --git a/include/beast/http/string_body.hpp b/include/beast/http/string_body.hpp index faee6943..41df300c 100644 --- a/include/beast/http/string_body.hpp +++ b/include/beast/http/string_body.hpp @@ -54,14 +54,9 @@ struct string_body template explicit - reader(message< - isRequest, string_body, Fields> const& msg) + reader(message const& msg, error_code& ec) : body_(msg.body) - { - } - - void - init(error_code& ec) { ec.assign(0, ec.category()); } @@ -73,12 +68,6 @@ struct string_body return {{const_buffers_type{ body_.data(), body_.size()}, false}}; } - - void - finish(error_code& ec) - { - ec.assign(0, ec.category()); - } }; #endif @@ -93,14 +82,10 @@ struct string_body public: template explicit - writer(message& m) + writer(message& m, + boost::optional content_length, + error_code& ec) : body_(m.body) - { - } - - void - init(boost::optional< - std::uint64_t> content_length, error_code& ec) { if(content_length) { @@ -115,6 +100,10 @@ struct string_body body_.reserve(static_cast< std::size_t>(*content_length)); } + else + { + ec.assign(0, ec.category()); + } } template diff --git a/include/beast/http/string_view_body.hpp b/include/beast/http/string_view_body.hpp index de57c48c..2a37f75c 100644 --- a/include/beast/http/string_view_body.hpp +++ b/include/beast/http/string_view_body.hpp @@ -55,14 +55,9 @@ struct string_view_body template explicit - reader(message< - isRequest, string_view_body, Fields> const& m) + reader(message const& m, error_code& ec) : body_(m.body) - { - } - - void - init(error_code& ec) { ec.assign(0, ec.category()); } @@ -73,12 +68,6 @@ struct string_view_body ec.assign(0, ec.category()); return {{{body_.data(), body_.size()}, false}}; } - - void - finish(error_code& ec) - { - ec.assign(0, ec.category()); - } }; #endif }; diff --git a/include/beast/http/type_traits.hpp b/include/beast/http/type_traits.hpp index 97ca0a5c..64d73b14 100644 --- a/include/beast/http/type_traits.hpp +++ b/include/beast/http/type_traits.hpp @@ -79,17 +79,19 @@ struct is_body_reader().init(std::declval()), std::declval>&>() = std::declval().get(std::declval()), - std::declval().finish(std::declval()), (void)0)>> : std::integral_constant::value && std::is_constructible const& >::value - > {}; + message const&, + error_code&>::value && + std::is_constructible const&, + error_code&>::value + > {}; #endif /** Determine if a @b Body type has a writer. @@ -120,19 +122,17 @@ struct is_body_writer : std::false_type {}; template struct is_body_writer().init( - std::declval>(), - std::declval()), std::declval().put( std::declval(), std::declval()), std::declval().finish( std::declval()), (void)0)>> : std::integral_constant&>::value - > + std::is_constructible&, + boost::optional, + error_code& + >::value> { }; #endif diff --git a/test/exemplars.cpp b/test/exemplars.cpp index 5ccc4c0d..304d3b71 100644 --- a/test/exemplars.cpp +++ b/test/exemplars.cpp @@ -62,23 +62,13 @@ public: /** Construct the reader. @param msg The message whose body is to be retrieved. - */ - template - explicit - BodyReader(message const& msg); - - /** Initialization. - - Called once immediately after construction. @param ec Set to the error, if any occurred. */ - void - init(error_code& ec) - { - // The specification requires this to indicate "no error" - ec = {}; - } + template + explicit + BodyReader(message const& msg, + error_code &ec); /** Returns the next buffer in the body. @@ -106,17 +96,6 @@ public: return boost::none; // for exposition only } - - /** Called after `get` indicates there are no more buffers. - - @param ec Set to the error, if any occurred. - */ - void - finish(error_code& ec) - { - // The specification requires this to indicate "no error" - ec = {}; - } }; //] @@ -137,19 +116,12 @@ struct BodyWriter */ template explicit - BodyWriter(message& msg); - - /** Initialization. - - Called once immediately before storing any buffers. - - @param content_length The content length if known, else `boost::none`. - - @param ec Set to the error, if any occurred. - */ - void - init(boost::optional content_length, error_code& ec) + BodyWriter(message& msg, + boost::optional content_length, + error_code& ec) { + boost::ignore_unused(msg, content_length); + // The specification requires this to indicate "no error" ec = {}; } diff --git a/test/http/write.cpp b/test/http/write.cpp index 8c6f790a..6ab516ae 100644 --- a/test/http/write.cpp +++ b/test/http/write.cpp @@ -49,13 +49,9 @@ public: template explicit - reader(message const& msg) + reader(message const& msg, error_code &ec) : body_(msg.body) - { - } - - void - init(error_code& ec) { ec.assign(0, ec.category()); } @@ -67,12 +63,6 @@ public: return {{const_buffers_type{ body_.data(), body_.size()}, false}}; } - - void - finish(error_code& ec) - { - ec.assign(0, ec.category()); - } }; }; @@ -104,13 +94,8 @@ public: template explicit reader(message const& msg) + Fields> const& msg, error_code& ec) : body_(msg.body) - { - } - - void - init(error_code& ec) { ec.assign(0, ec.category()); } @@ -125,12 +110,6 @@ public: std::integral_constant{}); } - void - finish(error_code& ec) - { - ec.assign(0, ec.category()); - } - private: boost::optional> get( @@ -248,13 +227,9 @@ public: template explicit - reader(message const& msg) + reader(message const& msg, error_code& ec) : body_(msg.body) - { - } - - void - init(error_code& ec) { body_.fc_.fail(ec); } @@ -269,12 +244,6 @@ public: return {{const_buffers_type{ body_.s_.data() + n_++, 1}, true}}; } - - void - finish(error_code& ec) - { - body_.fc_.fail(ec); - } }; };