From 3803c38dbd48928c1beb4729e8d25c3be92ee081 Mon Sep 17 00:00:00 2001 From: Vinnie Falco Date: Sun, 4 Jun 2017 12:38:42 -0700 Subject: [PATCH] Refactor header status, reason, and target (API Change): * header::result is a family of functions to replace header::status * header interface now uses status enum and also ints * reason-phrase is no longer stored unless the user explicitly requests it. * When serializing, the standard reason is used for the corresponding status code unless the user has changed it. --- CHANGELOG.md | 2 + doc/4_2_message.qbk | 3 +- doc/4_3_streams.qbk | 3 +- doc/4_4_serializer_streams.qbk | 4 +- doc/4_5_parser_streams.qbk | 3 +- doc/4_8_custom_parsers.qbk | 2 +- doc/6_1_http_message.qbk | 4 +- doc/images/message.png | Bin 39902 -> 37882 bytes doc/quickref.xml | 1 + examples/http_async_server.hpp | 9 +- examples/http_sync_server.hpp | 7 +- include/beast/http/fields.hpp | 31 ++- include/beast/http/impl/error.ipp | 2 + include/beast/http/impl/fields.ipp | 25 +- include/beast/http/impl/message.ipp | 28 ++- include/beast/http/impl/serializer.ipp | 9 +- include/beast/http/impl/status.ipp | 131 ++++++++++- include/beast/http/message.hpp | 294 +++++++++++++++--------- include/beast/http/parser.hpp | 8 +- include/beast/http/status.hpp | 70 +++++- include/beast/http/verb.hpp | 2 +- include/beast/websocket/impl/accept.ipp | 3 +- include/beast/websocket/impl/stream.ipp | 10 +- test/http/design.cpp | 9 +- test/http/fields.cpp | 12 +- test/http/message.cpp | 46 +++- test/http/parser.cpp | 4 +- test/http/status.cpp | 76 ++++++ test/http/test_parser.hpp | 4 +- test/http/write.cpp | 6 +- 30 files changed, 588 insertions(+), 220 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bbfb7372..ac1404b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ API Changes: * Refactor method and verb * Canonicalize string_view parameter types +* Tidy up empty_body writer error +* Refactor header status, reason, and target -------------------------------------------------------------------------------- diff --git a/doc/4_2_message.qbk b/doc/4_2_message.qbk index 0005d07d..d21064de 100644 --- a/doc/4_2_message.qbk +++ b/doc/4_2_message.qbk @@ -147,8 +147,7 @@ objects: ``` response res; res.version = 11; // HTTP/1.1 - res.status = 200; - res.reason("OK"); + res.result(status::ok); res.body = "Hello, world!"; res.fields.insert("Server", "Beast"); res.fields.insert("Content-Length", res.body.size()); diff --git a/doc/4_3_streams.qbk b/doc/4_3_streams.qbk index 847e4f48..10be7a88 100644 --- a/doc/4_3_streams.qbk +++ b/doc/4_3_streams.qbk @@ -128,8 +128,7 @@ the number of octets received prior to the server closing the connection: { response res; res.version = 11; - res.status = 200; - res.reason("OK"); + res.result(status::ok); res.fields.insert("Server", "Beast"); res.body = "Hello, world!"; diff --git a/doc/4_4_serializer_streams.qbk b/doc/4_4_serializer_streams.qbk index 3494a20a..acf36bdb 100644 --- a/doc/4_4_serializer_streams.qbk +++ b/doc/4_4_serializer_streams.qbk @@ -164,7 +164,7 @@ send_expect_100_continue( { response res; read(stream, buffer, res); - if(res.status != 100) + if(res.result() != status::continue_) { // The server indicated that it will not // accept the request, so skip sending the body. @@ -229,7 +229,7 @@ send_cgi_response( // allowing serialization to use manually provided buffers. message res; - res.status = 200; + res.result(status::ok); res.version = 11; res.fields.insert("Server", "Beast"); res.fields.insert("Transfer-Encoding", "chunked"); diff --git a/doc/4_5_parser_streams.qbk b/doc/4_5_parser_streams.qbk index 6002b28c..6b2fa291 100644 --- a/doc/4_5_parser_streams.qbk +++ b/doc/4_5_parser_streams.qbk @@ -197,8 +197,7 @@ receive_expect_100_continue( // send 100 response response res; res.version = 11; - res.status = 100; - res.reason("Continue"); + res.result(status::continue_); res.fields.insert("Server", "test"); write(stream, res, ec); if(ec) diff --git a/doc/4_8_custom_parsers.qbk b/doc/4_8_custom_parsers.qbk index 45542076..75a9a9af 100644 --- a/doc/4_8_custom_parsers.qbk +++ b/doc/4_8_custom_parsers.qbk @@ -56,7 +56,7 @@ class custom_parser /// Called after receiving the start-line (isRequest == false). void on_response( - int status, // The status-code + int code, // The status-code string_view reason, // The obsolete reason-phrase int version, // The HTTP-version error_code& ec); // The error returned to the caller, if any diff --git a/doc/6_1_http_message.qbk b/doc/6_1_http_message.qbk index 08f4c4bd..45a0cbb3 100644 --- a/doc/6_1_http_message.qbk +++ b/doc/6_1_http_message.qbk @@ -256,13 +256,13 @@ struct header string_view reason() const { - return fields.reason(); + return fields.reason_impl(); } void reason(string_view s) { - fields.reason(s); + fields.reason_impl(s); } Fields fields; diff --git a/doc/images/message.png b/doc/images/message.png index 6e96476279502237174403268bbc83aee06f368a..159df8c0ca3e2128f6635121027b0cb515c38beb 100644 GIT binary patch delta 37219 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 BMyvn; diff --git a/doc/quickref.xml b/doc/quickref.xml index a0b9bd4d..06f36e68 100644 --- a/doc/quickref.xml +++ b/doc/quickref.xml @@ -88,6 +88,7 @@ connection error status + status_class verb Type Traits diff --git a/examples/http_async_server.hpp b/examples/http_async_server.hpp index 9d359232..82998566 100644 --- a/examples/http_async_server.hpp +++ b/examples/http_async_server.hpp @@ -234,8 +234,7 @@ private: if(! boost::filesystem::exists(path)) { response res; - res.status = 404; - res.reason("Not Found"); + res.result(status::not_found); res.version = req_.version; res.fields.insert("Server", "http_async_server"); res.fields.insert("Content-Type", "text/html"); @@ -249,8 +248,7 @@ private: try { resp_type res; - res.status = 200; - res.reason("OK"); + res.result(status::ok); res.version = req_.version; res.fields.insert("Server", "http_async_server"); res.fields.insert("Content-Type", mime_type(path)); @@ -263,8 +261,7 @@ private: catch(std::exception const& e) { response res; - res.status = 500; - res.reason("Internal Error"); + res.result(status::internal_server_error); res.version = req_.version; res.fields.insert("Server", "http_async_server"); res.fields.insert("Content-Type", "text/html"); diff --git a/examples/http_sync_server.hpp b/examples/http_sync_server.hpp index 4b80cb47..b26db6b0 100644 --- a/examples/http_sync_server.hpp +++ b/examples/http_sync_server.hpp @@ -164,8 +164,7 @@ private: if(! boost::filesystem::exists(path)) { response res; - res.status = 404; - res.reason("Not Found"); + res.result(status::not_found); res.version = req.version; res.fields.insert("Server", "http_sync_server"); res.fields.insert("Content-Type", "text/html"); @@ -179,7 +178,7 @@ private: try { resp_type res; - res.status = 200; + res.result(status::ok); res.reason("OK"); res.version = req.version; res.fields.insert("Server", "http_sync_server"); @@ -193,7 +192,7 @@ private: catch(std::exception const& e) { response res; - res.status = 500; + res.result(status::internal_server_error); res.reason("Internal Error"); res.version = req.version; res.fields.insert("Server", "http_sync_server"); diff --git a/include/beast/http/fields.hpp b/include/beast/http/fields.hpp index aa9869a9..bf61a758 100644 --- a/include/beast/http/fields.hpp +++ b/include/beast/http/fields.hpp @@ -286,33 +286,48 @@ private: #endif string_view - method_string() const; + method_impl() const + { + return (*this)[":method"]; + } void - method_string(string_view s); + method_impl(string_view s) + { + if(s.empty()) + this->erase(":method"); + else + this->replace(":method", s); + } string_view - target() const + target_impl() const { return (*this)[":target"]; } void - target(string_view s) + target_impl(string_view s) { - return this->replace(":target", s); + if(s.empty()) + this->erase(":target"); + else + return this->replace(":target", s); } string_view - reason() const + reason_impl() const { return (*this)[":reason"]; } void - reason(string_view s) + reason_impl(string_view s) { - return this->replace(":reason", s); + if(s.empty()) + this->erase(":reason"); + else + this->replace(":reason", s); } }; diff --git a/include/beast/http/impl/error.ipp b/include/beast/http/impl/error.ipp index 72eb5d38..72330914 100644 --- a/include/beast/http/impl/error.ipp +++ b/include/beast/http/impl/error.ipp @@ -42,6 +42,8 @@ public: case error::end_of_stream: return "end of stream"; case error::partial_message: return "partial message"; case error::need_more: return "need more"; + case error::unexpected_body: return "unexpected body"; + case error::need_buffer: return "need buffer"; case error::buffer_overflow: return "buffer overflow"; case error::bad_line_ending: return "bad line ending"; case error::bad_method: return "bad method"; diff --git a/include/beast/http/impl/fields.ipp b/include/beast/http/impl/fields.ipp index 9e23de45..fae1a451 100644 --- a/include/beast/http/impl/fields.ipp +++ b/include/beast/http/impl/fields.ipp @@ -230,8 +230,7 @@ erase(string_view name) template void basic_fields:: -insert(string_view name, - string_view value) +insert(string_view name, string_view value) { value = detail::trim(value); auto const p = alloc_traits::allocate(this->member(), 1); @@ -243,33 +242,13 @@ insert(string_view name, template void basic_fields:: -replace(string_view name, - string_view value) +replace(string_view name, string_view value) { value = detail::trim(value); erase(name); insert(name, value); } -template -string_view -basic_fields:: -method_string() const -{ - return (*this)[":method"]; -} - -template -void -basic_fields:: -method_string(string_view s) -{ - if(s.empty()) - this->erase(":method"); - else - this->replace(":method", s); -} - } // http } // beast diff --git a/include/beast/http/impl/message.ipp b/include/beast/http/impl/message.ipp index 71df4b0f..881b20d3 100644 --- a/include/beast/http/impl/message.ipp +++ b/include/beast/http/impl/message.ipp @@ -30,7 +30,7 @@ get_method_string() const { if(method_ != verb::unknown) return to_string(method_); - return fields.method_string(); + return fields.method_impl(); } template @@ -43,7 +43,7 @@ set_method(verb v) BOOST_THROW_EXCEPTION( std::invalid_argument{"unknown verb"}); method_ = v; - fields.method_string({}); + fields.method_impl({}); } template @@ -54,9 +54,21 @@ set_method(string_view s) { method_ = string_to_verb(s); if(method_ != verb::unknown) - fields.method_string({}); + fields.method_impl({}); else - fields.method_string(s); + fields.method_impl(s); +} + +template +template +string_view +header:: +get_reason() const +{ + auto const s = fields.reason_impl(); + if(! s.empty()) + return s; + return obsolete_reason(result_); } template @@ -79,8 +91,8 @@ swap( { using std::swap; swap(a.version, b.version); - swap(a.status, b.status); swap(a.fields, b.fields); + swap(a.result_, b.result_); } template @@ -242,9 +254,9 @@ prepare(message& msg, operator()(message& msg, detail::prepare_info const& pi) const { - if((msg.status / 100 ) != 1 && - msg.status != 204 && - msg.status != 304) + if(to_status_class(msg.result()) != status_class::informational && + msg.result() != status::no_content && + msg.result() != status::not_modified) { msg.fields.insert( "Content-Length", *pi.content_length); diff --git a/include/beast/http/impl/serializer.ipp b/include/beast/http/impl/serializer.ipp index dcf812c9..7801e382 100644 --- a/include/beast/http/impl/serializer.ipp +++ b/include/beast/http/impl/serializer.ipp @@ -23,6 +23,7 @@ void write_start_line(std::ostream& os, header const& msg) { + // VFALCO This should all be done without dynamic allocation BOOST_ASSERT(msg.version == 10 || msg.version == 11); os << msg.method() << " " << msg.target(); switch(msg.version) @@ -37,18 +38,14 @@ void write_start_line(std::ostream& os, header const& msg) { + // VFALCO This should all be done without dynamic allocation BOOST_ASSERT(msg.version == 10 || msg.version == 11); switch(msg.version) { case 10: os << "HTTP/1.0 "; break; case 11: os << "HTTP/1.1 "; break; } - auto const reason = msg.reason(); - if(reason.empty()) - os << msg.status << " " << msg.reason() << "\r\n"; - else - os << msg.status << " " << - obsolete_reason(static_cast(msg.status)) << "\r\n"; + os << msg.result_int() << " " << msg.reason() << "\r\n"; } template diff --git a/include/beast/http/impl/status.ipp b/include/beast/http/impl/status.ipp index 93f9e104..5a7d579b 100644 --- a/include/beast/http/impl/status.ipp +++ b/include/beast/http/impl/status.ipp @@ -8,10 +8,101 @@ #ifndef BEAST_HTTP_IMPL_STATUS_IPP #define BEAST_HTTP_IMPL_STATUS_IPP +#include + namespace beast { namespace http { namespace detail { +template +status +int_to_status(int v) +{ + switch(static_cast(v)) + { + // 1xx + case status::continue_: + case status::switching_protocols: + case status::processing: + // [[fallthrough]] + + // 2xx + case status::ok: + case status::created: + case status::accepted: + case status::non_authoritative_information: + case status::no_content: + case status::reset_content: + case status::partial_content: + case status::multi_status: + case status::already_reported: + case status::im_used: + // [[fallthrough]] + + // 3xx + case status::multiple_choices: + case status::moved_permanently: + case status::found: + case status::see_other: + case status::not_modified: + case status::use_proxy: + case status::temporary_redirect: + case status::permanent_redirect: + // [[fallthrough]] + + // 4xx + case status::bad_request: + case status::unauthorized: + case status::payment_required: + case status::forbidden: + case status::not_found: + case status::method_not_allowed: + case status::not_acceptable: + case status::proxy_authentication_required: + case status::request_timeout: + case status::conflict: + case status::gone: + case status::length_required: + case status::precondition_failed: + case status::payload_too_large: + case status::uri_too_long: + case status::unsupported_media_type: + case status::range_not_satisfiable: + case status::expectation_failed: + case status::misdirected_request: + case status::unprocessable_entity: + case status::locked: + case status::failed_dependency: + case status::upgrade_required: + case status::precondition_required: + case status::too_many_requests: + case status::request_header_fields_too_large: + case status::connection_closed_without_response: + case status::unavailable_for_legal_reasons: + case status::client_closed_request: + // [[fallthrough]] + + // 5xx + case status::internal_server_error: + case status::not_implemented: + case status::bad_gateway: + case status::service_unavailable: + case status::gateway_timeout: + case status::http_version_not_supported: + case status::variant_also_negotiates: + case status::insufficient_storage: + case status::loop_detected: + case status::not_extended: + case status::network_authentication_required: + case status::network_connect_timeout_error: + return static_cast(v); + + default: + break; + } + return status::unknown; +} + template string_view status_to_string(int v) @@ -92,11 +183,49 @@ status_to_string(int v) default: break; } - return "Unknown Status"; + return ""; +} + +template +status_class +to_status_class(int v) +{ + switch(v / 100) + { + case 1: return status_class::informational; + case 2: return status_class::successful; + case 3: return status_class::redirection; + case 4: return status_class::client_error; + case 5: return status_class::server_error; + default: + break; + } + return status_class::unknown; } } // detail +inline +status +int_to_status(int v) +{ + return detail::int_to_status(v); +} + +inline +status_class +to_status_class(int v) +{ + return detail::to_status_class(v); +} + +inline +status_class +to_status_class(status v) +{ + return to_status_class(static_cast(v)); +} + inline string_view obsolete_reason(status v) diff --git a/include/beast/http/message.hpp b/include/beast/http/message.hpp index bb15d847..e997ba3a 100644 --- a/include/beast/http/message.hpp +++ b/include/beast/http/message.hpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -58,104 +59,6 @@ struct header /// The type representing the fields. using fields_type = Fields; - /** The HTTP version. - - This holds both the major and minor version numbers, - using these formulas: - @code - major = version / 10; - minor = version % 10; - @endcode - */ - int version; - - /** Return the request-method verb. - - If the request-method is not one of the recognized verbs, - @ref verb::unknown is returned. Callers may use @ref method_string - to retrieve the exact text. - - @note This function is only available if `isRequest == true`. - - @see @ref method_string - */ - verb - method() const - { - return method_; - } - - /** Set the request-method verb. - - This function will set the method for requests to one - of the known verbs. - - @param v The request method verb to set. - This may not be @ref verb::unknown. - - @throw std::invalid_argument when `v == verb::unknown`. - */ - void - method(verb v) - { - set_method(v); - } - - /** Return the request-method as a string. - - @note This function is only available if `isRequest == true`. - - @see @ref method - */ - string_view - method_string() const - { - return get_method_string(); - } - - /** Set the request-method using a string. - - This function will set the method for requests to a verb - if the string matches a known verb, otherwise it will - store a copy of the passed string as the method. - - @param s A string representing the request method. - - @note This function is only available if `isRequest == true`. - */ - void - method(string_view s) - { - set_method(s); - } - - /** Return the Request Target - - @note This function is only available if `isRequest == true`. - */ - auto - target() const -> - decltype(std::declval().target()) const - { - return fields.target(); - } - - /** Set the Request Target - - @param value A value that represents the request method. - - @note This function is only available if `isRequest == true`. - */ - template - void - target(Value&& value) - { - fields.target(std::forward(value)); - } - - /// The HTTP field values. - fields_type fields; - /// Default constructor header() = default; @@ -198,13 +101,106 @@ struct header { } + /** The HTTP-version. + + This holds both the major and minor version numbers, + using these formulas: + @code + int major = version / 10; + int minor = version % 10; + @endcode + */ + int version; + + /// The HTTP field values. + fields_type fields; + + /** Return the request-method verb. + + If the request-method is not one of the recognized verbs, + @ref verb::unknown is returned. Callers may use @ref method_string + to retrieve the exact text. + + @note This function is only available if `isRequest == true`. + + @see @ref method_string + */ + verb + method() const + { + return method_; + } + + /** Set the request-method verb. + + This function will set the method for requests to a known verb. + + @param v The request method verb to set. + This may not be @ref verb::unknown. + + @throw std::invalid_argument when `v == verb::unknown`. + */ + void + method(verb v) + { + set_method(v); + } + + /** Return the request-method string. + + @note This function is only available if `isRequest == true`. + + @see @ref method + */ + string_view + method_string() const + { + return get_method_string(); + } + + /** Set the request-method string. + + This function will set the method for requests to a verb + if the string matches a known verb, otherwise it will + store a copy of the passed string as the method. + + @param s A string representing the request-method. + + @note This function is only available if `isRequest == true`. + */ + void + method(string_view s) + { + set_method(s); + } + + /** Returns the request-target string. + + @note This function is only available if `isRequest == true`. + */ + string_view + target() const + { + return fields.target_impl(); + } + + /** Set the request-target string. + + @param s A string representing the request-target. + + @note This function is only available if `isRequest == true`. + */ + void + target(string_view s) + { + fields.target_impl(s); + } + private: - template + template friend void - swap( - header& m1, - header& m2); + swap(header& m1, header& m2); template string_view @@ -256,7 +252,7 @@ struct header /// The HTTP field values. fields_type fields; - /// Default constructor + /// Default constructor. header() = default; /// Move constructor @@ -293,11 +289,62 @@ struct header } #endif - /** The Response Status-Code. + /** The response status-code result. + + If the actual status code is not a known code, this + function returns @ref status::unknown. Use @ref result_int + to return the raw status code as a number. @note This member is only available if `isRequest == false`. */ - int status; + status + result() const + { + return int_to_status( + static_cast(result_)); + } + + /** Set the response status-code result. + + @param v The code to set. + + @note This member is only available if `isRequest == false`. + */ + void + result(status v) + { + result_ = v; + } + + /** Set the raw status-code result 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 + status codes, the function @ref result will return + @ref status::unknown. Use @ref result_int to obtain the + original raw status-code. + + @param v The status-code integer to set. + */ + void + result(int v) + { + result_ = static_cast(v); + } + + /** The response status-code result 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 if `isRequest == false`. + */ + int + result_int() const + { + return static_cast(result_); + } + /** Return the Reason-Phrase. @@ -305,26 +352,47 @@ struct header @note This function is only available if `isRequest == false`. */ - auto - reason() const -> - decltype(std::declval().reason()) const + string_view + reason() const { - return fields.reason(); + return get_reason(); } /** Set the Reason-Phrase + This function sets a custom reason-phrase to a copy of + the string passed in. Normally it is not necessary to set + the reason phrase on an outgoing response object; the + implementation will automatically use the standard reason + text for the corresponding status code. + + To clear a previously set custom phrase, pass an empty + string. This will restore the default standard reason text + based on the status code used when serializing. + + The Reason-Phrase is obsolete as of rfc7230. + @param value A value that represents the reason phrase. @note This function is only available if `isRequest == false`. */ - template void - reason(Value&& value) + reason(string_view s) { - fields.reason(std::forward(value)); + fields.reason_impl(s); } - + +private: + template + friend + void + swap(header& m1, header& m2); + + template + string_view + get_reason() const; + + status result_; }; /** A container for a complete HTTP message. diff --git a/include/beast/http/parser.hpp b/include/beast/http/parser.hpp index 13edb2e1..1f770602 100644 --- a/include/beast/http/parser.hpp +++ b/include/beast/http/parser.hpp @@ -153,10 +153,10 @@ private: } void - on_response(int status, string_view reason, + on_response(int code, string_view reason, int version, error_code&) { - h_.status = status; + h_.result(code); h_.version = version; h_.reason(reason); } @@ -341,11 +341,11 @@ private: } void - on_response(int status, + on_response(int code, string_view reason, int version, error_code&) { - m_.status = status; + m_.result(code); m_.version = version; m_.reason(reason); } diff --git a/include/beast/http/status.hpp b/include/beast/http/status.hpp index 3fcfd7ce..3e35fc30 100644 --- a/include/beast/http/status.hpp +++ b/include/beast/http/status.hpp @@ -15,8 +15,17 @@ namespace beast { namespace http { -enum class status : int +enum class status : unsigned short { + /** An unknown status-code. + + This value indicates that the value for the status code + is not in the list of commonly recognized status codes. + Callers interested in the exactly value should use the + interface which provides the raw integer. + */ + unknown = 0, + continue_ = 100, switching_protocols = 101, processing = 102, @@ -85,13 +94,66 @@ enum class status : int network_connect_timeout_error = 599 }; -/// Returns the obsolete reason-phrase text for a status code. +/** Represents the class of a status-code. +*/ +enum class status_class : int +{ + /// Unknown status-class + unknown = 0, + + /// The request was received, continuing processing. + informational = 1, + + /// The request was successfully received, understood, and accepted. + successful = 2, + + /// Further action needs to be taken in order to complete the request. + redirection = 3, + + /// The request contains bad syntax or cannot be fulfilled. + client_error = 4, + + /// The server failed to fulfill an apparently valid request. + server_error = 5, +}; + +/** Converts the integer to a known status-code. + + If the integer does not match a known status code, + @ref status::unknown is returned. +*/ +status +int_to_status(int v); + +/** Convert an integer to a status_class. + + @param v The integer representing a status code. + + @return The status class. If the integer does not match + a known status class, @ref status_class::unknown is returned. +*/ +status_class +to_status_class(int v); + +/** Convert a status_code to a status_class. + + @param v The status code to convert. + + @return The status class. +*/ +status_class +to_status_class(status v); + +/** Returns the obsolete reason-phrase text for a status code. + + @param v The status code to use. +*/ string_view obsolete_reason(status v); -/// Outputs the reason phrase of a status code to a stream. +/// Outputs the standard reason phrase of a status code to a stream. std::ostream& -operator<<(std::ostream& os, status v); +operator<<(std::ostream&, status); } // http } // beast diff --git a/include/beast/http/verb.hpp b/include/beast/http/verb.hpp index a77020b9..2e303223 100644 --- a/include/beast/http/verb.hpp +++ b/include/beast/http/verb.hpp @@ -128,7 +128,7 @@ enum class verb /** Converts a string to the request method verb. If the string does not match a known request method, - `boost::none` is returned. + @ref verb::unknown is returned. */ verb string_to_verb(string_view s); diff --git a/include/beast/websocket/impl/accept.ipp b/include/beast/websocket/impl/accept.ipp index c9c761fb..944e7725 100644 --- a/include/beast/websocket/impl/accept.ipp +++ b/include/beast/websocket/impl/accept.ipp @@ -148,7 +148,8 @@ operator()(error_code ec, bool again) // sent response case 1: d.state = 99; - if(d.res.status != 101) + if(d.res.result() != + http::status::switching_protocols) ec = error::handshake_failed; if(! ec) { diff --git a/include/beast/websocket/impl/stream.ipp b/include/beast/websocket/impl/stream.ipp index dc533ffa..865f302a 100644 --- a/include/beast/websocket/impl/stream.ipp +++ b/include/beast/websocket/impl/stream.ipp @@ -112,7 +112,7 @@ do_accept(http::header const& req, http::write(stream_, res, ec); if(ec) return; - if(res.status != 101) + if(res.result() != http::status::switching_protocols) { ec = error::handshake_failed; // VFALCO TODO Respect keep alive setting, perform @@ -216,7 +216,7 @@ build_response(http::header const& req, [&](std::string const& text) { response_type res; - res.status = 400; + res.result(http::status::bad_request); res.version = req.version; res.body = text; prepare(res); @@ -246,7 +246,7 @@ build_response(http::header const& req, if(version != "13") { response_type res; - res.status = 426; + res.result(http::status::upgrade_required); res.version = req.version; res.fields.insert("Sec-WebSocket-Version", "13"); prepare(res); @@ -263,7 +263,7 @@ build_response(http::header const& req, pmd_negotiate( res.fields, unused, offer, pmd_opts_); } - res.status = 101; + res.result(http::status::switching_protocols); res.version = req.version; res.fields.insert("Upgrade", "websocket"); res.fields.insert("Connection", "upgrade"); @@ -286,7 +286,7 @@ do_response(http::header const& res, { if(res.version < 11) return false; - if(res.status != 101) + if(res.result() != http::status::switching_protocols) return false; if(! is_upgrade(res)) return false; diff --git a/test/http/design.cpp b/test/http/design.cpp index 3eb30b34..2aef02f9 100644 --- a/test/http/design.cpp +++ b/test/http/design.cpp @@ -46,7 +46,7 @@ class custom_parser /// Called after receiving the start-line (isRequest == false). void on_response( - int status, // The status-code + int code, // The status-code string_view reason, // The obsolete reason-phrase int version, // The HTTP-version error_code& ec); // The error returned to the caller, if any @@ -238,7 +238,7 @@ public: read(stream, buffer, res, ec); if(ec) return; - if(res.status != 100) + if(res.result() != status::continue_) { // The server indicated that it will not // accept the request, so skip sending the body. @@ -291,8 +291,7 @@ public: // send 100 response response res; res.version = 11; - res.status = 100; - res.reason("Continue"); + res.result(status::continue_); res.fields.insert("Server", "test"); write(stream, res, ec); if(ec) @@ -383,7 +382,7 @@ public: // allowing serialization to use manually provided buffers. message res; - res.status = 200; + res.result(status::ok); res.version = 11; res.fields.insert("Server", "Beast"); res.fields.insert("Transfer-Encoding", "chunked"); diff --git a/test/http/fields.cpp b/test/http/fields.cpp index 3dfd23e7..9607b91f 100644 --- a/test/http/fields.cpp +++ b/test/http/fields.cpp @@ -103,12 +103,12 @@ public: testMethodString() { f_t f; - f.method_string("CRY"); - BEAST_EXPECTS(f.method_string() == "CRY", f.method_string()); - f.method_string("PUT"); - BEAST_EXPECTS(f.method_string() == "PUT", f.method_string()); - f.method_string({}); - BEAST_EXPECTS(f.method_string().empty(), f.method_string()); + f.method_impl("CRY"); + BEAST_EXPECTS(f.method_impl() == "CRY", f.method_impl()); + f.method_impl("PUT"); + BEAST_EXPECTS(f.method_impl() == "PUT", f.method_impl()); + f.method_impl({}); + BEAST_EXPECTS(f.method_impl().empty(), f.method_impl()); } void run() override diff --git a/test/http/message.cpp b/test/http/message.cpp index 0de2542b..e006f31c 100644 --- a/test/http/message.cpp +++ b/test/http/message.cpp @@ -262,19 +262,20 @@ public: { message m1; message m2; - m1.status = 200; + m1.result(status::ok); m1.version = 10; m1.body = "1"; m1.fields.insert("h", "v"); - m2.status = 404; - m2.reason("OK"); + m2.result(status::not_found); m2.body = "2"; m2.version = 11; swap(m1, m2); - BEAST_EXPECT(m1.status == 404); - BEAST_EXPECT(m2.status == 200); - BEAST_EXPECT(m1.reason() == "OK"); - BEAST_EXPECT(m2.reason().empty()); + BEAST_EXPECT(m1.result() == status::not_found); + BEAST_EXPECT(m1.result_int() == 404); + BEAST_EXPECT(m2.result() == status::ok); + BEAST_EXPECT(m2.result_int() == 200); + BEAST_EXPECT(m1.reason() == "Not Found"); + BEAST_EXPECT(m2.reason() == "OK"); BEAST_EXPECT(m1.version == 11); BEAST_EXPECT(m2.version == 10); BEAST_EXPECT(m1.body == "2"); @@ -321,6 +322,35 @@ public: scheck("XYZ"); } + void + testStatus() + { + header h; + h.result(200); + BEAST_EXPECT(h.result_int() == 200); + BEAST_EXPECT(h.result() == status::ok); + h.result(status::switching_protocols); + BEAST_EXPECT(h.result_int() == 101); + BEAST_EXPECT(h.result() == status::switching_protocols); + h.result(1); + BEAST_EXPECT(h.result_int() == 1); + BEAST_EXPECT(h.result() == status::unknown); + } + + void + testReason() + { + header h; + h.result(status::ok); + BEAST_EXPECT(h.reason() == "OK"); + h.reason("Pepe"); + BEAST_EXPECT(h.reason() == "Pepe"); + h.result(status::not_found); + BEAST_EXPECT(h.reason() == "Pepe"); + h.reason({}); + BEAST_EXPECT(h.reason() == "Not Found"); + } + void run() override { @@ -331,6 +361,8 @@ public: testSwap(); testSpecialMembers(); testMethod(); + testStatus(); + testReason(); } }; diff --git a/test/http/parser.cpp b/test/http/parser.cpp index 8ace8e0f..1b1ce19a 100644 --- a/test/http/parser.cpp +++ b/test/http/parser.cpp @@ -182,7 +182,7 @@ public: BEAST_EXPECT(p.need_eof()); BEAST_EXPECT(p.content_length() == boost::none); BEAST_EXPECT(m.version == 10); - BEAST_EXPECT(m.status == 200); + BEAST_EXPECT(m.result() == status::ok); BEAST_EXPECT(m.reason() == "OK"); BEAST_EXPECT(m.fields["Server"] == "test"); BEAST_EXPECT(m.body == "Hello, world!"); @@ -209,7 +209,7 @@ public: BEAST_EXPECT(p.is_chunked()); BEAST_EXPECT(p.content_length() == boost::none); BEAST_EXPECT(m.version == 11); - BEAST_EXPECT(m.status == 200); + BEAST_EXPECT(m.result() == status::ok); BEAST_EXPECT(m.reason() == "OK"); BEAST_EXPECT(m.fields["Server"] == "test"); BEAST_EXPECT(m.fields["Transfer-Encoding"] == "chunked"); diff --git a/test/http/status.cpp b/test/http/status.cpp index e7389d5a..69cdcbff 100644 --- a/test/http/status.cpp +++ b/test/http/status.cpp @@ -20,6 +20,82 @@ public: void testStatus() { + auto const check = [&](status s, int i, status_class sc) + { + BEAST_EXPECT(int_to_status(i) == s); + BEAST_EXPECT(to_status_class(i) == sc); + BEAST_EXPECT(to_status_class(int_to_status(i)) == sc); + }; + check(status::continue_ ,100, status_class::informational); + check(status::switching_protocols ,101, status_class::informational); + check(status::processing ,102, status_class::informational); + + check(status::ok ,200, status_class::successful); + check(status::created ,201, status_class::successful); + check(status::accepted ,202, status_class::successful); + check(status::non_authoritative_information ,203, status_class::successful); + check(status::no_content ,204, status_class::successful); + check(status::reset_content ,205, status_class::successful); + check(status::partial_content ,206, status_class::successful); + check(status::multi_status ,207, status_class::successful); + check(status::already_reported ,208, status_class::successful); + check(status::im_used ,226, status_class::successful); + + check(status::multiple_choices ,300, status_class::redirection); + check(status::moved_permanently ,301, status_class::redirection); + check(status::found ,302, status_class::redirection); + check(status::see_other ,303, status_class::redirection); + check(status::not_modified ,304, status_class::redirection); + check(status::use_proxy ,305, status_class::redirection); + check(status::temporary_redirect ,307, status_class::redirection); + check(status::permanent_redirect ,308, status_class::redirection); + + check(status::bad_request ,400, status_class::client_error); + check(status::unauthorized ,401, status_class::client_error); + check(status::payment_required ,402, status_class::client_error); + check(status::forbidden ,403, status_class::client_error); + check(status::not_found ,404, status_class::client_error); + check(status::method_not_allowed ,405, status_class::client_error); + check(status::not_acceptable ,406, status_class::client_error); + check(status::proxy_authentication_required ,407, status_class::client_error); + check(status::request_timeout ,408, status_class::client_error); + check(status::conflict ,409, status_class::client_error); + check(status::gone ,410, status_class::client_error); + check(status::length_required ,411, status_class::client_error); + check(status::precondition_failed ,412, status_class::client_error); + check(status::payload_too_large ,413, status_class::client_error); + check(status::uri_too_long ,414, status_class::client_error); + check(status::unsupported_media_type ,415, status_class::client_error); + check(status::range_not_satisfiable ,416, status_class::client_error); + check(status::expectation_failed ,417, status_class::client_error); + check(status::misdirected_request ,421, status_class::client_error); + check(status::unprocessable_entity ,422, status_class::client_error); + check(status::locked ,423, status_class::client_error); + check(status::failed_dependency ,424, status_class::client_error); + check(status::upgrade_required ,426, status_class::client_error); + check(status::precondition_required ,428, status_class::client_error); + check(status::too_many_requests ,429, status_class::client_error); + check(status::request_header_fields_too_large ,431, status_class::client_error); + check(status::connection_closed_without_response ,444, status_class::client_error); + check(status::unavailable_for_legal_reasons ,451, status_class::client_error); + check(status::client_closed_request ,499, status_class::client_error); + + check(status::internal_server_error ,500, status_class::server_error); + check(status::not_implemented ,501, status_class::server_error); + check(status::bad_gateway ,502, status_class::server_error); + check(status::service_unavailable ,503, status_class::server_error); + check(status::gateway_timeout ,504, status_class::server_error); + check(status::http_version_not_supported ,505, status_class::server_error); + check(status::variant_also_negotiates ,506, status_class::server_error); + check(status::insufficient_storage ,507, status_class::server_error); + check(status::loop_detected ,508, status_class::server_error); + check(status::not_extended ,510, status_class::server_error); + check(status::network_authentication_required ,511, status_class::server_error); + check(status::network_connect_timeout_error ,599, status_class::server_error); + + BEAST_EXPECT(to_status_class(1) == status_class::unknown); + BEAST_EXPECT(to_status_class(status::unknown) == status_class::unknown); + auto const good = [&](status v) { diff --git a/test/http/test_parser.hpp b/test/http/test_parser.hpp index 0f88ba06..f0de6e05 100644 --- a/test/http/test_parser.hpp +++ b/test/http/test_parser.hpp @@ -62,11 +62,11 @@ public: } void - on_response(int status_, + on_response(int code, string_view reason_, int version_, error_code& ec) { - status = status_; + status = code; reason = std::string( reason_.data(), reason_.size()); version = version_; diff --git a/test/http/write.cpp b/test/http/write.cpp index e79d7907..a603cfd8 100644 --- a/test/http/write.cpp +++ b/test/http/write.cpp @@ -292,7 +292,7 @@ public: { message m; m.version = 10; - m.status = 200; + m.result(status::ok); m.reason("OK"); m.fields.insert("Server", "test"); m.fields.insert("Content-Length", "5"); @@ -311,7 +311,7 @@ public: { message m; m.version = 11; - m.status = 200; + m.result(status::ok); m.reason("OK"); m.fields.insert("Server", "test"); m.fields.insert("Transfer-Encoding", "chunked"); @@ -786,7 +786,7 @@ public: message m0; m0.version = 11; - m0.status = 200; + m0.result(status::ok); m0.reason("OK"); m0.fields.insert("Server", "test"); m0.body.s = "Hello, world!\n";