File indexing completed on 2025-12-16 09:44:00
0001
0002
0003
0004
0005
0006
0007
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
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
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 }
0425 }
0426 }
0427
0428 #endif