Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 09:44:00

0001 //
0002 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
0003 //
0004 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0005 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 // Official repository: https://github.com/boostorg/beast
0008 //
0009 
0010 #ifndef BOOST_BEAST_HTTP_IMPL_MESSAGE_HPP
0011 #define BOOST_BEAST_HTTP_IMPL_MESSAGE_HPP
0012 
0013 #include <boost/beast/core/error.hpp>
0014 #include <boost/assert.hpp>
0015 #include <boost/throw_exception.hpp>
0016 #include <stdexcept>
0017 
0018 namespace boost {
0019 namespace beast {
0020 namespace http {
0021 
0022 template<class Fields>
0023 template<class Arg1, class... ArgN, class>
0024 header<true, Fields>::
0025 header(Arg1&& arg1, ArgN&&... argn)
0026     : Fields(std::forward<Arg1>(arg1),
0027         std::forward<ArgN>(argn)...)
0028 {
0029 }
0030 
0031 template<class Fields>
0032 verb
0033 header<true, Fields>::
0034 method() const
0035 {
0036     return method_;
0037 }
0038 
0039 template<class Fields>
0040 void
0041 header<true, Fields>::
0042 method(verb v)
0043 {
0044     if(v == verb::unknown)
0045         BOOST_THROW_EXCEPTION(
0046             std::invalid_argument{"unknown method"});
0047     method_ = v;
0048     this->set_method_impl({});
0049 }
0050 
0051 template<class Fields>
0052 string_view
0053 header<true, Fields>::
0054 method_string() const
0055 {
0056     if(method_ != verb::unknown)
0057         return to_string(method_);
0058     return this->get_method_impl();
0059 }
0060 
0061 template<class Fields>
0062 void
0063 header<true, Fields>::
0064 method_string(string_view s)
0065 {
0066     method_ = string_to_verb(s);
0067     if(method_ != verb::unknown)
0068         this->set_method_impl({});
0069     else
0070         this->set_method_impl(s);
0071 }
0072 
0073 template<class Fields>
0074 string_view
0075 header<true, Fields>::
0076 target() const
0077 {
0078     return this->get_target_impl();
0079 }
0080 
0081 template<class Fields>
0082 void
0083 header<true, Fields>::
0084 target(string_view s)
0085 {
0086     this->set_target_impl(s);
0087 }
0088 
0089 template<class Fields>
0090 void
0091 swap(
0092     header<true, Fields>& h1,
0093     header<true, Fields>& h2)
0094 {
0095     using std::swap;
0096     swap(
0097         static_cast<Fields&>(h1),
0098         static_cast<Fields&>(h2));
0099     swap(h1.version_, h2.version_);
0100     swap(h1.method_, h2.method_);
0101 }
0102 
0103 //------------------------------------------------------------------------------
0104 
0105 template<class Fields>
0106 template<class Arg1, class... ArgN, class>
0107 header<false, Fields>::
0108 header(Arg1&& arg1, ArgN&&... argn)
0109     : Fields(std::forward<Arg1>(arg1),
0110         std::forward<ArgN>(argn)...)
0111 {
0112 }
0113 
0114 template<class Fields>
0115 status
0116 header<false, Fields>::
0117 result() const
0118 {
0119     return int_to_status(
0120         static_cast<int>(result_));
0121 }
0122 
0123 template<class Fields>
0124 void
0125 header<false, Fields>::
0126 result(status v)
0127 {
0128     result_ = v;
0129 }
0130 
0131 template<class Fields>
0132 void
0133 header<false, Fields>::
0134 result(unsigned v)
0135 {
0136     if(v > 999)
0137         BOOST_THROW_EXCEPTION(
0138             std::invalid_argument{
0139                 "invalid status-code"});
0140     result_ = static_cast<status>(v);
0141 }
0142 
0143 template<class Fields>
0144 unsigned
0145 header<false, Fields>::
0146 result_int() const
0147 {
0148     return static_cast<unsigned>(result_);
0149 }
0150 
0151 template<class Fields>
0152 string_view
0153 header<false, Fields>::
0154 reason() const
0155 {
0156     auto const s = this->get_reason_impl();
0157     if(! s.empty())
0158         return s;
0159     return obsolete_reason(result_);
0160 }
0161 
0162 template<class Fields>
0163 void
0164 header<false, Fields>::
0165 reason(string_view s)
0166 {
0167     this->set_reason_impl(s);
0168 }
0169 
0170 template<class Fields>
0171 void
0172 swap(
0173     header<false, Fields>& h1,
0174     header<false, Fields>& h2)
0175 {
0176     using std::swap;
0177     swap(
0178         static_cast<Fields&>(h1),
0179         static_cast<Fields&>(h2));
0180     swap(h1.version_, h2.version_);
0181     swap(h1.result_, h2.result_);
0182 }
0183 
0184 //------------------------------------------------------------------------------
0185 
0186 template<bool isRequest, class Body, class Fields>
0187 template<class... BodyArgs>
0188 message<isRequest, Body, Fields>::
0189 message(header_type&& h, BodyArgs&&... body_args)
0190     : header_type(std::move(h))
0191     , boost::empty_value<
0192         typename Body::value_type>(boost::empty_init_t(),
0193             std::forward<BodyArgs>(body_args)...)
0194 {
0195 }
0196 
0197 template<bool isRequest, class Body, class Fields>
0198 template<class... BodyArgs>
0199 message<isRequest, Body, Fields>::
0200 message(header_type const& h, BodyArgs&&... body_args)
0201     : header_type(h)
0202     , boost::empty_value<
0203         typename Body::value_type>(boost::empty_init_t(),
0204             std::forward<BodyArgs>(body_args)...)
0205 {
0206 }
0207 
0208 template<bool isRequest, class Body, class Fields>
0209 template<class Version, class>
0210 message<isRequest, Body, Fields>::
0211 message(verb method, string_view target, Version version)
0212     : header_type(method, target, version)
0213 {
0214 }
0215 
0216 template<bool isRequest, class Body, class Fields>
0217 template<class Version, class BodyArg, class>
0218 message<isRequest, Body, Fields>::
0219 message(verb method, string_view target,
0220         Version version, BodyArg&& body_arg)
0221     : header_type(method, target, version)
0222     , boost::empty_value<
0223         typename Body::value_type>(boost::empty_init_t(),
0224             std::forward<BodyArg>(body_arg))
0225 {
0226 }
0227 
0228 template<bool isRequest, class Body, class Fields>
0229 template<class Version, class BodyArg, class FieldsArg, class>
0230 message<isRequest, Body, Fields>::
0231 message(
0232     verb method, string_view target, Version version,
0233     BodyArg&& body_arg,
0234     FieldsArg&& fields_arg)
0235     : header_type(method, target, version,
0236         std::forward<FieldsArg>(fields_arg))
0237     , boost::empty_value<
0238         typename Body::value_type>(boost::empty_init_t(),
0239             std::forward<BodyArg>(body_arg))
0240 {
0241 }
0242 
0243 template<bool isRequest, class Body, class Fields>
0244 template<class Version, class>
0245 message<isRequest, Body, Fields>::
0246 message(status result, Version version)
0247     : header_type(result, version)
0248 {
0249 }
0250 
0251 template<bool isRequest, class Body, class Fields>
0252 template<class Version, class BodyArg, class>
0253 message<isRequest, Body, Fields>::
0254 message(status result, Version version,
0255     BodyArg&& body_arg)
0256     : header_type(result, version)
0257     , boost::empty_value<
0258         typename Body::value_type>(boost::empty_init_t(),
0259             std::forward<BodyArg>(body_arg))
0260 {
0261 }
0262 
0263 template<bool isRequest, class Body, class Fields>
0264 template<class Version, class BodyArg, class FieldsArg, class>
0265 message<isRequest, Body, Fields>::
0266 message(status result, Version version,
0267     BodyArg&& body_arg, FieldsArg&& fields_arg)
0268     : header_type(result, version,
0269         std::forward<FieldsArg>(fields_arg))
0270     , boost::empty_value<
0271         typename Body::value_type>(boost::empty_init_t(),
0272             std::forward<BodyArg>(body_arg))
0273 {
0274 }
0275 
0276 template<bool isRequest, class Body, class Fields>
0277 message<isRequest, Body, Fields>::
0278 message(std::piecewise_construct_t)
0279 {
0280 }
0281 
0282 template<bool isRequest, class Body, class Fields>
0283 template<class... BodyArgs>
0284 message<isRequest, Body, Fields>::
0285 message(std::piecewise_construct_t,
0286         std::tuple<BodyArgs...> body_args)
0287     : message(std::piecewise_construct,
0288         body_args,
0289         mp11::make_index_sequence<
0290             sizeof...(BodyArgs)>{})
0291 {
0292 }
0293 
0294 template<bool isRequest, class Body, class Fields>
0295 template<class... BodyArgs, class... FieldsArgs>
0296 message<isRequest, Body, Fields>::
0297 message(std::piecewise_construct_t,
0298     std::tuple<BodyArgs...> body_args,
0299     std::tuple<FieldsArgs...> fields_args)
0300     : message(std::piecewise_construct,
0301         body_args,
0302         fields_args,
0303         mp11::make_index_sequence<
0304             sizeof...(BodyArgs)>{},
0305         mp11::make_index_sequence<
0306             sizeof...(FieldsArgs)>{})
0307 {
0308 }
0309 
0310 template<bool isRequest, class Body, class Fields>
0311 void
0312 message<isRequest, Body, Fields>::
0313 chunked(bool value)
0314 {
0315     this->set_chunked_impl(value);
0316     this->set_content_length_impl(boost::none);
0317 }
0318 
0319 template<bool isRequest, class Body, class Fields>
0320 void
0321 message<isRequest, Body, Fields>::
0322 content_length(
0323     boost::optional<std::uint64_t> const& value)
0324 {
0325     this->set_content_length_impl(value);
0326     this->set_chunked_impl(false);
0327 }
0328 
0329 template<bool isRequest, class Body, class Fields>
0330 boost::optional<std::uint64_t>
0331 message<isRequest, Body, Fields>::
0332 payload_size() const
0333 {
0334     return payload_size(detail::is_body_sized<Body>{});
0335 }
0336 
0337 template<bool isRequest, class Body, class Fields>
0338 bool
0339 message<isRequest, Body, Fields>::
0340 need_eof(std::false_type) const
0341 {
0342     // VFALCO Do we need a way to let the caller say "the body is intentionally skipped"?
0343     if( this->result() == status::no_content ||
0344         this->result() == status::not_modified ||
0345         to_status_class(this->result()) ==
0346             status_class::informational ||
0347         has_content_length() ||
0348         chunked())
0349         return ! keep_alive();
0350     return true;
0351 }
0352 
0353 template<bool isRequest, class Body, class Fields>
0354 void
0355 message<isRequest, Body, Fields>::
0356 prepare_payload(std::true_type)
0357 {
0358     auto const n = payload_size();
0359     if(this->method() == verb::trace && (! n || *n > 0))
0360         BOOST_THROW_EXCEPTION(std::invalid_argument{
0361             "invalid request body"});
0362     if(n)
0363     {
0364         if(*n > 0 ||
0365             this->method() == verb::options ||
0366             this->method() == verb::put ||
0367             this->method() == verb::post)
0368         {
0369             this->content_length(n);
0370         }
0371         else
0372         {
0373             this->chunked(false);
0374         }
0375     }
0376     else if(this->version() == 11)
0377     {
0378         this->chunked(true);
0379     }
0380     else
0381     {
0382         this->chunked(false);
0383     }
0384 }
0385 
0386 template<bool isRequest, class Body, class Fields>
0387 void
0388 message<isRequest, Body, Fields>::
0389 prepare_payload(std::false_type)
0390 {
0391     auto const n = payload_size();
0392     if( (! n || *n > 0) && (
0393         (status_class(this->result()) == status_class::informational ||
0394         this->result() == status::no_content ||
0395         this->result() == status::not_modified)))
0396     {
0397         // The response body MUST be empty for this case
0398         BOOST_THROW_EXCEPTION(std::invalid_argument{
0399             "invalid response body"});
0400     }
0401     if(n)
0402         this->content_length(n);
0403     else if(this->version() == 11)
0404         this->chunked(true);
0405     else
0406         this->chunked(false);
0407 }
0408 
0409 //------------------------------------------------------------------------------
0410 
0411 template<bool isRequest, class Body, class Fields>
0412 void
0413 swap(
0414     message<isRequest, Body, Fields>& m1,
0415     message<isRequest, Body, Fields>& m2)
0416 {
0417     using std::swap;
0418     swap(
0419         static_cast<header<isRequest, Fields>&>(m1),
0420         static_cast<header<isRequest, Fields>&>(m2));
0421     swap(m1.body(), m2.body());
0422 }
0423 
0424 } // http
0425 } // beast
0426 } // boost
0427 
0428 #endif