// // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // Official repository: https://github.com/boostorg/beast // #ifndef BOOST_BEAST_HTTP_IMPL_MESSAGE_HPP #define BOOST_BEAST_HTTP_IMPL_MESSAGE_HPP #include #include #include #include namespace boost { namespace beast { namespace http { template template header:: header(Arg1&& arg1, ArgN&&... argn) : Fields(std::forward(arg1), std::forward(argn)...) { } template verb header:: method() const { return method_; } template void header:: method(verb v) { if(v == verb::unknown) BOOST_THROW_EXCEPTION( std::invalid_argument{"unknown method"}); method_ = v; 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 void header:: method_string(string_view s) { method_ = string_to_verb(s); if(method_ != verb::unknown) this->set_method_impl({}); else this->set_method_impl(s); } template string_view header:: target() const { return this->get_target_impl(); } template 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 status header:: result() const { return int_to_status( static_cast(result_)); } template void header:: result(status v) { result_ = v; } template void header:: result(unsigned v) { if(v > 999) BOOST_THROW_EXCEPTION( std::invalid_argument{ "invalid status-code"}); result_ = static_cast(v); } template unsigned header:: result_int() const { return static_cast(result_); } template string_view header:: reason() const { auto const s = this->get_reason_impl(); if(! s.empty()) return s; return obsolete_reason(result_); } template 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_); } //------------------------------------------------------------------------------ template template message:: message(header_type&& h, BodyArgs&&... body_args) : header_type(std::move(h)) , boost::empty_value< typename Body::value_type>(boost::empty_init_t(), std::forward(body_args)...) { } template template message:: message(header_type const& h, BodyArgs&&... body_args) : header_type(h) , boost::empty_value< typename Body::value_type>(boost::empty_init_t(), std::forward(body_args)...) { } template template message:: message(verb method, string_view target, Version version) : header_type(method, target, version) { } template template message:: message(verb method, string_view target, Version version, BodyArg&& body_arg) : header_type(method, target, version) , boost::empty_value< typename Body::value_type>(boost::empty_init_t(), std::forward(body_arg)) { } template template message:: message( verb method, string_view target, Version version, BodyArg&& body_arg, FieldsArg&& fields_arg) : header_type(method, target, version, std::forward(fields_arg)) , boost::empty_value< typename Body::value_type>(boost::empty_init_t(), std::forward(body_arg)) { } template template message:: message(status result, Version version) : header_type(result, version) { } template template message:: message(status result, Version version, BodyArg&& body_arg) : header_type(result, version) , boost::empty_value< typename Body::value_type>(boost::empty_init_t(), std::forward(body_arg)) { } template template message:: message(status result, Version version, BodyArg&& body_arg, FieldsArg&& fields_arg) : header_type(result, version, std::forward(fields_arg)) , boost::empty_value< typename Body::value_type>(boost::empty_init_t(), std::forward(body_arg)) { } template message:: message(std::piecewise_construct_t) { } template template message:: message(std::piecewise_construct_t, std::tuple body_args) : message(std::piecewise_construct, body_args, mp11::make_index_sequence< sizeof...(BodyArgs)>{}) { } template template message:: message(std::piecewise_construct_t, std::tuple body_args, std::tuple fields_args) : message(std::piecewise_construct, body_args, fields_args, mp11::make_index_sequence< sizeof...(BodyArgs)>{}, mp11::make_index_sequence< sizeof...(FieldsArgs)>{}) { } template void message:: chunked(bool value) { this->set_chunked_impl(value); this->set_content_length_impl(boost::none); } template void message:: content_length( boost::optional const& value) { this->set_content_length_impl(value); this->set_chunked_impl(false); } template boost::optional message:: payload_size() const { return payload_size(detail::is_body_sized{}); } template bool message:: need_eof(std::false_type) const { // VFALCO Do we need a way to let the caller say "the body is intentionally skipped"? if( this->result() == status::no_content || this->result() == status::not_modified || to_status_class(this->result()) == status_class::informational || has_content_length() || chunked()) return ! keep_alive(); return true; } template void message:: prepare_payload(std::true_type) { auto const n = payload_size(); if(this->method() == verb::trace && (! n || *n > 0)) BOOST_THROW_EXCEPTION(std::invalid_argument{ "invalid request body"}); if(n) { if(*n > 0 || this->method() == verb::options || this->method() == verb::put || this->method() == verb::post) { this->content_length(n); } else { this->chunked(false); } } else if(this->version() == 11) { this->chunked(true); } else { this->chunked(false); } } template void message:: prepare_payload(std::false_type) { auto const n = payload_size(); if( (! n || *n > 0) && ( (status_class(this->result()) == status_class::informational || this->result() == status::no_content || this->result() == status::not_modified))) { // The response body MUST be empty for this case BOOST_THROW_EXCEPTION(std::invalid_argument{ "invalid response body"}); } if(n) this->content_length(n); else if(this->version() == 11) this->chunked(true); else this->chunked(false); } //------------------------------------------------------------------------------ template void swap( message& m1, message& m2) { using std::swap; swap( static_cast&>(m1), static_cast&>(m2)); swap(m1.body(), m2.body()); } } // http } // beast } // boost #endif