From f363654300e043c08ec5e0fd0816d7a579793264 Mon Sep 17 00:00:00 2001 From: Vinnie Falco Date: Tue, 6 Jun 2017 16:20:59 -0700 Subject: [PATCH] Tidy up basic_fields, header, and concepts --- CHANGELOG.md | 2 + doc/concept/FieldSequence.qbk | 79 ++++++++---- include/beast/http/fields.hpp | 26 ++-- include/beast/http/impl/fields.ipp | 14 ++- include/beast/http/impl/message.ipp | 184 ++++++++++++++++++++-------- include/beast/http/message.hpp | 100 +++------------ include/beast/http/parser.hpp | 15 ++- 7 files changed, 253 insertions(+), 167 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d65443a..bbfd5855 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ Version 50 * Use allocator more in basic_fields * Fix basic_fields allocator awareness * Use field in basic_fields and call sites +* Use field in basic_parser +* Tidy up basic_fields, header, and field concepts API Changes: diff --git a/doc/concept/FieldSequence.qbk b/doc/concept/FieldSequence.qbk index ead9f0a9..a8a5b82a 100644 --- a/doc/concept/FieldSequence.qbk +++ b/doc/concept/FieldSequence.qbk @@ -64,39 +64,70 @@ In this table: [/ +/** OutputFields -[section:Fields Fields] + Can be serialized by `beast::http::serializer` +*/ + public: + // This algorithm produces a set of buffers + // corresponding to the serialized representation + // of the fields + // + struct reader + { + using const_buffers_type = implementation-defined -A type meeting the requirements of [*Fields] represents a container -used to store HTTP header fields. + ... + }; -In this table: + protected: + string_view method_impl() const; + string_view target_impl() const; + string_view reason_impl() const; -* `X` denotes a type that meets the requirements of [*Fields]. - -* `c` is a value of type `X const`. + bool close_impl () const; + bool chunked_impl () const; + bool content_length_impl () const; -[table FieldSequence requirements -[[expression][type][semantics, pre/post-conditions]] -[ - [] - [] - [ - ] -] -] -[endsect] +/** InputFields -Operations we'd like to perform + Can be parsed by `beast::http::parser` +*/ + public: + void insert (field f, string_view value); + void insert (string_view name, string_view value); -Determine if a field exists - bool exists(field f) const; - bool exists(string_view s) const; - - iterator find(field f) const; - iterator find(string_view s); + protected: + void method_impl (string_view s); + void target_impl (string_view s); + void reason_impl (string_view s); + + +/** Fields + + Has a container interface and supports input and output. + `beast::http:basic_fields` is a model. +*/ + + public: + bool exists(field f) const; + bool exists(string_view s) const; + + iterator find(field f) const; + iterator find(string_view s); + + std::size_t erase (field f); + std::size_t erase (string_view s); + iterator erase (iterator); + + protected: + void content_length_impl(std::uint64_t n); + void connection_impl(close_t); + void connection_impl(keep_alive_t); + void connection_impl(upgrade_t); + void chunked_impl(); ] diff --git a/include/beast/http/fields.hpp b/include/beast/http/fields.hpp index 23da7894..34b45d92 100644 --- a/include/beast/http/fields.hpp +++ b/include/beast/http/fields.hpp @@ -338,45 +338,57 @@ public: swap(basic_fields& lhs, basic_fields& rhs); protected: + + //-------------------------------------------------------------------------- // - // for `header + // for serializing // /** Returns the stored request-method string. @note This is called by the @ref header implementation. */ - string_view method_impl() const; + string_view get_method_impl() const; /** Returns the stored request-target string. @note This is called by the @ref header implementation. */ - string_view target_impl() const; + string_view get_target_impl() const; /** Returns the stored obsolete reason-phrase string. @note This is called by the @ref header implementation. */ - string_view reason_impl() const; + string_view get_reason_impl() const; + + //-------------------------------------------------------------------------- + // + // for parsing + // /** Set or clear the stored request-method string. @note This is called by the @ref header implementation. */ - void method_impl(string_view s); + void set_method_impl(string_view s); /** Set or clear the stored request-target string. @note This is called by the @ref header implementation. */ - void target_impl(string_view s); + void set_target_impl(string_view s); /** Set or clear the stored obsolete reason-phrase string. @note This is called by the @ref header implementation. */ - void reason_impl(string_view s); + void set_reason_impl(string_view s); + + //-------------------------------------------------------------------------- + // + // for container + // /** Set the Content-Length field to the specified value. diff --git a/include/beast/http/impl/fields.ipp b/include/beast/http/impl/fields.ipp index af5f7628..dac43055 100644 --- a/include/beast/http/impl/fields.ipp +++ b/include/beast/http/impl/fields.ipp @@ -365,7 +365,7 @@ template inline string_view basic_fields:: -method_impl() const +get_method_impl() const { return method_; } @@ -374,7 +374,7 @@ template inline string_view basic_fields:: -target_impl() const +get_target_impl() const { return target_or_reason_; } @@ -383,7 +383,7 @@ template inline string_view basic_fields:: -reason_impl() const +get_reason_impl() const { return target_or_reason_; } @@ -392,7 +392,7 @@ template inline void basic_fields:: -method_impl(string_view s) +set_method_impl(string_view s) { realloc_string(method_, s); } @@ -401,7 +401,7 @@ template inline void basic_fields:: -target_impl(string_view s) +set_target_impl(string_view s) { realloc_string(target_or_reason_, s); } @@ -410,11 +410,13 @@ template inline void basic_fields:: -reason_impl(string_view s) +set_reason_impl(string_view s) { realloc_string(target_or_reason_, s); } +//--- + template inline void diff --git a/include/beast/http/impl/message.ipp b/include/beast/http/impl/message.ipp index f4effbae..b6b3dba9 100644 --- a/include/beast/http/impl/message.ipp +++ b/include/beast/http/impl/message.ipp @@ -19,60 +19,176 @@ namespace beast { namespace http { template -template -string_view +template header:: -get_method_string() const +header(Arg1&& arg1, ArgN&&... argn) + : Fields(std::forward(arg1), + std::forward(argn)...) { - if(method_ != verb::unknown) - return to_string(method_); - return this->method_impl(); } template -template +inline +verb +header:: +method() const +{ + return method_; +} + +template void header:: -set_method(verb v) +method(verb v) { if(v == verb::unknown) BOOST_THROW_EXCEPTION( std::invalid_argument{"unknown verb"}); method_ = v; - this->method_impl({}); + this->set_method_impl({}); +} + +template +string_view +header:: +method_string() const +{ + if(method_ != verb::unknown) + return to_string(method_); + return this->get_method_impl(); } template -template void header:: -set_method(string_view s) +method(string_view s) { method_ = string_to_verb(s); if(method_ != verb::unknown) - this->method_impl({}); + this->set_method_impl({}); else - this->method_impl(s); + this->set_method_impl(s); +} + +template +inline +string_view +header:: +target() const +{ + return this->get_target_impl(); +} + +template +inline +void +header:: +target(string_view s) +{ + this->set_target_impl(s); +} + +template +void +swap( + header& h1, + header& h2) +{ + using std::swap; + swap( + static_cast(h1), + static_cast(h2)); + swap(h1.version, h2.version); + swap(h1.method_, h2.method_); +} + +//------------------------------------------------------------------------------ + +template +template +header:: +header(Arg1&& arg1, ArgN&&... argn) + : Fields(std::forward(arg1), + std::forward(argn)...) +{ +} +template +inline +status +header:: +result() const +{ + return int_to_status( + static_cast(result_)); +} + +template +inline +void +header:: +result(status v) +{ + result_ = v; +} + +template +inline +void +header:: +result(unsigned v) +{ + if(v > 999) + BOOST_THROW_EXCEPTION( + std::invalid_argument{ + "invalid result-code"}); + result_ = static_cast(v); +} + +template +inline +unsigned +header:: +result_int() const +{ + return static_cast(result_); } template -template string_view header:: -get_reason() const +reason() const { - auto const s = this->reason_impl(); + auto const s = this->get_reason_impl(); if(! s.empty()) return s; return obsolete_reason(result_); } +template +inline +void +header:: +reason(string_view s) +{ + this->set_reason_impl(s); +} + +template +void +swap( + header& h1, + header& h2) +{ + using std::swap; + swap( + static_cast(h1), + static_cast(h2)); + swap(h1.version, h2.version); + swap(h1.result_, h2.result_); +} + //------------------------------------------------------------------------------ -namespace detail { - -} // detail - template bool message:: @@ -239,34 +355,6 @@ prepare_payload(std::false_type) //------------------------------------------------------------------------------ -template -void -swap( - header& h1, - header& h2) -{ - using std::swap; - swap( - static_cast(h1), - static_cast(h2)); - swap(h1.version, h2.version); - swap(h1.method_, h2.method_); -} - -template -void -swap( - header& h1, - header& h2) -{ - using std::swap; - swap( - static_cast(h1), - static_cast(h2)); - swap(h1.version, h2.version); - swap(h1.result_, h2.result_); -} - template void swap( diff --git a/include/beast/http/message.hpp b/include/beast/http/message.hpp index 3f28665b..314bb0cc 100644 --- a/include/beast/http/message.hpp +++ b/include/beast/http/message.hpp @@ -104,11 +104,7 @@ struct header : Fields typename std::decay::type, header>::value>::type> explicit - header(Arg1&& arg1, ArgN&&... argn) - : Fields(std::forward(arg1), - std::forward(argn)...) - { - } + header(Arg1&& arg1, ArgN&&... argn); /** Return the request-method verb. @@ -121,10 +117,7 @@ struct header : Fields @see @ref method_string */ verb - method() const - { - return method_; - } + method() const; /** Set the request-method verb. @@ -136,10 +129,7 @@ struct header : Fields @throw std::invalid_argument when `v == verb::unknown`. */ void - method(verb v) - { - set_method(v); - } + method(verb v); /** Return the request-method string. @@ -148,10 +138,7 @@ struct header : Fields @see @ref method */ string_view - method_string() const - { - return get_method_string(); - } + method_string() const; /** Set the request-method string. @@ -164,20 +151,14 @@ struct header : Fields @note This function is only available when `isRequest == true`. */ void - method(string_view s) - { - set_method(s); - } + method(string_view s); /** Returns the request-target string. @note This function is only available when `isRequest == true`. */ string_view - target() const - { - return this->target_impl(); - } + target() const; /** Set the request-target string. @@ -186,10 +167,7 @@ struct header : Fields @note This function is only available when `isRequest == true`. */ void - target(string_view s) - { - this->target_impl(s); - } + target(string_view s); private: template @@ -200,18 +178,6 @@ private: void swap(header& m1, header& m2); - template - string_view - get_method_string() const; - - template - void - set_method(verb v); - - template - void - set_method(string_view v); - verb method_ = verb::unknown; }; @@ -277,11 +243,7 @@ struct header : Fields typename std::decay::type, header>::value>::type> explicit - header(Arg1&& arg1, ArgN&&... argn) - : Fields(std::forward(arg1), - std::forward(argn)...) - { - } + header(Arg1&& arg1, ArgN&&... argn); #endif /** The response status-code result. @@ -293,25 +255,18 @@ struct header : Fields @note This member is only available when `isRequest == false`. */ status - result() const - { - return int_to_status( - static_cast(result_)); - } + result() const; - /** Set the response status-code result. + /** Set the response status-code. @param v The code to set. @note This member is only available when `isRequest == false`. */ void - result(status v) - { - result_ = v; - } + result(status v); - /** Set the raw status-code result as an integer. + /** Set the response status-code as an integer. This sets the status code to the exact number passed in. If the number does not correspond to one of the known @@ -320,26 +275,21 @@ struct header : Fields original raw status-code. @param v The status-code integer to set. + + @throw std::invalid_argument if `v > 999`. */ void - result(int v) - { - result_ = static_cast(v); - } + result(unsigned v); - /** The response status-code result expressed as an integer. + /** The response status-code expressed as an integer. This returns the raw status code as an integer, even when that code is not in the list of known status codes. @note This member is only available when `isRequest == false`. */ - int - result_int() const - { - return static_cast(result_); - } - + unsigned + result_int() const; /** Return the response reason-phrase. @@ -348,10 +298,7 @@ struct header : Fields @note This function is only available when `isRequest == false`. */ string_view - reason() const - { - return get_reason(); - } + reason() const; /** Set the response reason-phrase (deprecated) @@ -372,10 +319,7 @@ struct header : Fields @note This function is only available when `isRequest == false`. */ void - reason(string_view s) - { - this->reason_impl(s); - } + reason(string_view s); private: template @@ -386,10 +330,6 @@ private: void swap(header& m1, header& m2); - template - string_view - get_reason() const; - status result_; }; diff --git a/include/beast/http/parser.hpp b/include/beast/http/parser.hpp index a3857ba8..d09bd5f4 100644 --- a/include/beast/http/parser.hpp +++ b/include/beast/http/parser.hpp @@ -208,11 +208,22 @@ private: string_view value, error_code&) { if(f != field::unknown) - // VFALCO Note we are not preserving the - // capitalization of the field name. + { + #if 1 + // This preserves capitalization of field names + if(to_string(f) == name) + m_.insert(f, value); + else + m_.insert(name, value); + #else + // This doesn't. m_.insert(f, value); + #endif + } else + { m_.insert(name, value); + } } void