summaryrefslogtreecommitdiff
path: root/boost/beast/http/impl/message.ipp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/beast/http/impl/message.ipp')
-rw-r--r--boost/beast/http/impl/message.ipp437
1 files changed, 437 insertions, 0 deletions
diff --git a/boost/beast/http/impl/message.ipp b/boost/beast/http/impl/message.ipp
new file mode 100644
index 0000000000..64d96eb6f1
--- /dev/null
+++ b/boost/beast/http/impl/message.ipp
@@ -0,0 +1,437 @@
+//
+// Copyright (c) 2016-2017 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_IPP
+#define BOOST_BEAST_HTTP_IMPL_MESSAGE_IPP
+
+#include <boost/beast/core/error.hpp>
+#include <boost/beast/core/detail/type_traits.hpp>
+#include <boost/assert.hpp>
+#include <boost/throw_exception.hpp>
+#include <stdexcept>
+
+namespace boost {
+namespace beast {
+namespace http {
+
+template<class Fields>
+template<class Arg1, class... ArgN, class>
+header<true, Fields>::
+header(Arg1&& arg1, ArgN&&... argn)
+ : Fields(std::forward<Arg1>(arg1),
+ std::forward<ArgN>(argn)...)
+{
+}
+
+template<class Fields>
+inline
+verb
+header<true, Fields>::
+method() const
+{
+ return method_;
+}
+
+template<class Fields>
+void
+header<true, Fields>::
+method(verb v)
+{
+ if(v == verb::unknown)
+ BOOST_THROW_EXCEPTION(
+ std::invalid_argument{"unknown method"});
+ method_ = v;
+ this->set_method_impl({});
+}
+
+template<class Fields>
+string_view
+header<true, Fields>::
+method_string() const
+{
+ if(method_ != verb::unknown)
+ return to_string(method_);
+ return this->get_method_impl();
+}
+
+template<class Fields>
+void
+header<true, Fields>::
+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<class Fields>
+inline
+string_view
+header<true, Fields>::
+target() const
+{
+ return this->get_target_impl();
+}
+
+template<class Fields>
+inline
+void
+header<true, Fields>::
+target(string_view s)
+{
+ this->set_target_impl(s);
+}
+
+template<class Fields>
+void
+swap(
+ header<true, Fields>& h1,
+ header<true, Fields>& h2)
+{
+ using std::swap;
+ swap(
+ static_cast<Fields&>(h1),
+ static_cast<Fields&>(h2));
+ swap(h1.version_, h2.version_);
+ swap(h1.method_, h2.method_);
+}
+
+//------------------------------------------------------------------------------
+
+template<class Fields>
+template<class Arg1, class... ArgN, class>
+header<false, Fields>::
+header(Arg1&& arg1, ArgN&&... argn)
+ : Fields(std::forward<Arg1>(arg1),
+ std::forward<ArgN>(argn)...)
+{
+}
+
+template<class Fields>
+inline
+status
+header<false, Fields>::
+result() const
+{
+ return int_to_status(
+ static_cast<int>(result_));
+}
+
+template<class Fields>
+inline
+void
+header<false, Fields>::
+result(status v)
+{
+ result_ = v;
+}
+
+template<class Fields>
+inline
+void
+header<false, Fields>::
+result(unsigned v)
+{
+ if(v > 999)
+ BOOST_THROW_EXCEPTION(
+ std::invalid_argument{
+ "invalid status-code"});
+ result_ = static_cast<status>(v);
+}
+
+template<class Fields>
+inline
+unsigned
+header<false, Fields>::
+result_int() const
+{
+ return static_cast<unsigned>(result_);
+}
+
+template<class Fields>
+string_view
+header<false, Fields>::
+reason() const
+{
+ auto const s = this->get_reason_impl();
+ if(! s.empty())
+ return s;
+ return obsolete_reason(result_);
+}
+
+template<class Fields>
+inline
+void
+header<false, Fields>::
+reason(string_view s)
+{
+ this->set_reason_impl(s);
+}
+
+template<class Fields>
+void
+swap(
+ header<false, Fields>& h1,
+ header<false, Fields>& h2)
+{
+ using std::swap;
+ swap(
+ static_cast<Fields&>(h1),
+ static_cast<Fields&>(h2));
+ swap(h1.version_, h2.version_);
+ swap(h1.result_, h2.result_);
+}
+
+//------------------------------------------------------------------------------
+
+template<bool isRequest, class Body, class Fields>
+template<class... BodyArgs>
+message<isRequest, Body, Fields>::
+message(header_type&& h, BodyArgs&&... body_args)
+ : header_type(std::move(h))
+ , beast::detail::empty_base_optimization<
+ typename Body::value_type>(
+ std::forward<BodyArgs>(body_args)...)
+{
+}
+
+template<bool isRequest, class Body, class Fields>
+template<class... BodyArgs>
+message<isRequest, Body, Fields>::
+message(header_type const& h, BodyArgs&&... body_args)
+ : header_type(h)
+ , beast::detail::empty_base_optimization<
+ typename Body::value_type>(
+ std::forward<BodyArgs>(body_args)...)
+{
+}
+
+template<bool isRequest, class Body, class Fields>
+template<class Version, class>
+message<isRequest, Body, Fields>::
+message(verb method, string_view target, Version version)
+ : header_type(method, target, version)
+{
+}
+
+template<bool isRequest, class Body, class Fields>
+template<class Version, class BodyArg, class>
+message<isRequest, Body, Fields>::
+message(verb method, string_view target,
+ Version version, BodyArg&& body_arg)
+ : header_type(method, target, version)
+ , beast::detail::empty_base_optimization<
+ typename Body::value_type>(
+ std::forward<BodyArg>(body_arg))
+{
+}
+
+template<bool isRequest, class Body, class Fields>
+template<class Version, class BodyArg, class FieldsArg, class>
+message<isRequest, Body, Fields>::
+message(
+ verb method, string_view target, Version version,
+ BodyArg&& body_arg,
+ FieldsArg&& fields_arg)
+ : header_type(method, target, version,
+ std::forward<FieldsArg>(fields_arg))
+ , beast::detail::empty_base_optimization<
+ typename Body::value_type>(
+ std::forward<BodyArg>(body_arg))
+{
+}
+
+template<bool isRequest, class Body, class Fields>
+template<class Version, class>
+message<isRequest, Body, Fields>::
+message(status result, Version version)
+ : header_type(result, version)
+{
+}
+
+template<bool isRequest, class Body, class Fields>
+template<class Version, class BodyArg, class>
+message<isRequest, Body, Fields>::
+message(status result, Version version,
+ BodyArg&& body_arg)
+ : header_type(result, version)
+ , beast::detail::empty_base_optimization<
+ typename Body::value_type>(
+ std::forward<BodyArg>(body_arg))
+{
+}
+
+template<bool isRequest, class Body, class Fields>
+template<class Version, class BodyArg, class FieldsArg, class>
+message<isRequest, Body, Fields>::
+message(status result, Version version,
+ BodyArg&& body_arg, FieldsArg&& fields_arg)
+ : header_type(result, version,
+ std::forward<FieldsArg>(fields_arg))
+ , beast::detail::empty_base_optimization<
+ typename Body::value_type>(
+ std::forward<BodyArg>(body_arg))
+{
+}
+
+template<bool isRequest, class Body, class Fields>
+message<isRequest, Body, Fields>::
+message(std::piecewise_construct_t)
+{
+}
+
+template<bool isRequest, class Body, class Fields>
+template<class... BodyArgs>
+message<isRequest, Body, Fields>::
+message(std::piecewise_construct_t,
+ std::tuple<BodyArgs...> body_args)
+ : message(std::piecewise_construct,
+ body_args,
+ beast::detail::make_index_sequence<
+ sizeof...(BodyArgs)>{})
+{
+}
+
+template<bool isRequest, class Body, class Fields>
+template<class... BodyArgs, class... FieldsArgs>
+message<isRequest, Body, Fields>::
+message(std::piecewise_construct_t,
+ std::tuple<BodyArgs...> body_args,
+ std::tuple<FieldsArgs...> fields_args)
+ : message(std::piecewise_construct,
+ body_args,
+ fields_args,
+ beast::detail::make_index_sequence<
+ sizeof...(BodyArgs)>{},
+ beast::detail::make_index_sequence<
+ sizeof...(FieldsArgs)>{})
+{
+}
+
+template<bool isRequest, class Body, class Fields>
+void
+message<isRequest, Body, Fields>::
+chunked(bool value)
+{
+ this->set_chunked_impl(value);
+ this->set_content_length_impl(boost::none);
+}
+
+template<bool isRequest, class Body, class Fields>
+void
+message<isRequest, Body, Fields>::
+content_length(
+ boost::optional<std::uint64_t> const& value)
+{
+ this->set_content_length_impl(value);
+ this->set_chunked_impl(false);
+}
+
+template<bool isRequest, class Body, class Fields>
+boost::optional<std::uint64_t>
+message<isRequest, Body, Fields>::
+payload_size() const
+{
+ return payload_size(detail::is_body_sized<Body>{});
+}
+
+template<bool isRequest, class Body, class Fields>
+bool
+message<isRequest, Body, Fields>::
+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<bool isRequest, class Body, class Fields>
+void
+message<isRequest, Body, Fields>::
+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<bool isRequest, class Body, class Fields>
+void
+message<isRequest, Body, Fields>::
+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<bool isRequest, class Body, class Fields>
+void
+swap(
+ message<isRequest, Body, Fields>& m1,
+ message<isRequest, Body, Fields>& m2)
+{
+ using std::swap;
+ swap(
+ static_cast<header<isRequest, Fields>&>(m1),
+ static_cast<header<isRequest, Fields>&>(m2));
+ swap(m1.body(), m2.body());
+}
+
+} // http
+} // beast
+} // boost
+
+#endif