File indexing completed on 2025-11-30 09:42:36
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_BEAST_HTTP_PARSER_HPP
0011 #define BOOST_BEAST_HTTP_PARSER_HPP
0012
0013 #include <boost/beast/http/parser_fwd.hpp>
0014
0015 #include <boost/beast/core/detail/config.hpp>
0016 #include <boost/beast/http/basic_parser.hpp>
0017 #include <boost/beast/http/message.hpp>
0018 #include <boost/beast/http/type_traits.hpp>
0019 #include <boost/optional.hpp>
0020 #include <boost/throw_exception.hpp>
0021 #include <cstdint>
0022 #include <functional>
0023 #include <memory>
0024 #include <type_traits>
0025 #include <utility>
0026
0027 namespace boost {
0028 namespace beast {
0029 namespace http {
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048 #if BOOST_BEAST_DOXYGEN
0049 template<
0050 bool isRequest,
0051 class Body,
0052 class Allocator = std::allocator<char>>
0053 #else
0054 template<
0055 bool isRequest,
0056 class Body,
0057 class Allocator>
0058 #endif
0059 class parser
0060 : public basic_parser<isRequest>
0061 {
0062 static_assert(is_body<Body>::value,
0063 "Body type requirements not met");
0064
0065 static_assert(is_body_reader<Body>::value,
0066 "BodyReader type requirements not met");
0067
0068 template<bool, class, class>
0069 friend class parser;
0070
0071 message<isRequest, Body, basic_fields<Allocator>> m_;
0072 typename Body::reader rd_;
0073 bool rd_inited_ = false;
0074 bool used_ = false;
0075
0076 std::function<void(
0077 std::uint64_t,
0078 string_view,
0079 error_code&)> cb_h_;
0080
0081 std::function<std::size_t(
0082 std::uint64_t,
0083 string_view,
0084 error_code&)> cb_b_;
0085
0086 public:
0087
0088 using value_type =
0089 message<isRequest, Body, basic_fields<Allocator>>;
0090
0091
0092 ~parser() = default;
0093
0094
0095 parser(parser const&) = delete;
0096
0097
0098 parser& operator=(parser const&) = delete;
0099
0100
0101 parser(parser&& other) = delete;
0102
0103
0104 parser();
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115 #if BOOST_BEAST_DOXYGEN
0116 template<class... Args>
0117 explicit
0118 parser(Args&&... args);
0119 #else
0120 template<class Arg1, class... ArgN,
0121 class = typename std::enable_if<
0122 ! detail::is_parser<typename
0123 std::decay<Arg1>::type>::value>::type>
0124 explicit
0125 parser(Arg1&& arg1, ArgN&&... argn);
0126 #endif
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159 #if BOOST_BEAST_DOXYGEN
0160 template<class OtherBody, class... Args>
0161 #else
0162 template<class OtherBody, class... Args,
0163 class = typename std::enable_if<
0164 ! std::is_same<Body, OtherBody>::value>::type>
0165 #endif
0166 explicit
0167 parser(parser<isRequest, OtherBody,
0168 Allocator>&& parser, Args&&... args);
0169
0170
0171
0172
0173
0174
0175 value_type const&
0176 get() const
0177 {
0178 return m_;
0179 }
0180
0181
0182
0183
0184
0185
0186 value_type&
0187 get()
0188 {
0189 return m_;
0190 }
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202 value_type
0203 release()
0204 {
0205 static_assert(std::is_move_constructible<decltype(m_)>::value,
0206 "MoveConstructible requirements not met");
0207 return std::move(m_);
0208 }
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244 template<class Callback>
0245 void
0246 on_chunk_header(Callback& cb)
0247 {
0248
0249
0250 BOOST_STATIC_ASSERT(! std::is_const<Callback>::value);
0251
0252
0253 BOOST_ASSERT(! rd_inited_);
0254
0255 cb_h_ = std::ref(cb);
0256 }
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282
0283
0284
0285
0286
0287
0288
0289
0290
0291
0292 template<class Callback>
0293 void
0294 on_chunk_body(Callback& cb)
0295 {
0296
0297
0298 BOOST_STATIC_ASSERT(! std::is_const<Callback>::value);
0299
0300
0301 BOOST_ASSERT(! rd_inited_);
0302
0303 cb_b_ = std::ref(cb);
0304 }
0305
0306 private:
0307 parser(std::true_type);
0308 parser(std::false_type);
0309
0310 template<class OtherBody, class... Args,
0311 class = typename std::enable_if<
0312 ! std::is_same<Body, OtherBody>::value>::type>
0313 parser(
0314 std::true_type,
0315 parser<isRequest, OtherBody, Allocator>&& parser,
0316 Args&&... args);
0317
0318 template<class OtherBody, class... Args,
0319 class = typename std::enable_if<
0320 ! std::is_same<Body, OtherBody>::value>::type>
0321 parser(
0322 std::false_type,
0323 parser<isRequest, OtherBody, Allocator>&& parser,
0324 Args&&... args);
0325
0326 template<class Arg1, class... ArgN,
0327 class = typename std::enable_if<
0328 ! detail::is_parser<typename
0329 std::decay<Arg1>::type>::value>::type>
0330 explicit
0331 parser(Arg1&& arg1, std::true_type, ArgN&&... argn);
0332
0333 template<class Arg1, class... ArgN,
0334 class = typename std::enable_if<
0335 ! detail::is_parser<typename
0336 std::decay<Arg1>::type>::value>::type>
0337 explicit
0338 parser(Arg1&& arg1, std::false_type, ArgN&&... argn);
0339
0340 void
0341 on_request_impl(
0342 verb method,
0343 string_view method_str,
0344 string_view target,
0345 int version,
0346 error_code& ec,
0347 std::true_type)
0348 {
0349
0350
0351
0352
0353
0354
0355 BOOST_ASSERT(! used_);
0356 if(used_)
0357 {
0358 BOOST_BEAST_ASSIGN_EC(ec, error::stale_parser);
0359 return;
0360 }
0361 used_ = true;
0362
0363 m_.target(target);
0364 if(method != verb::unknown)
0365 m_.method(method);
0366 else
0367 m_.method_string(method_str);
0368 m_.version(version);
0369 }
0370
0371 void
0372 on_request_impl(
0373 verb, string_view, string_view,
0374 int, error_code&, std::false_type)
0375 {
0376 }
0377
0378 void
0379 on_request_impl(
0380 verb method,
0381 string_view method_str,
0382 string_view target,
0383 int version,
0384 error_code& ec) override
0385 {
0386 this->on_request_impl(
0387 method, method_str, target, version, ec,
0388 std::integral_constant<bool, isRequest>{});
0389 }
0390
0391 void
0392 on_response_impl(
0393 int code,
0394 string_view reason,
0395 int version,
0396 error_code& ec,
0397 std::true_type)
0398 {
0399
0400
0401
0402
0403
0404
0405 BOOST_ASSERT(! used_);
0406 if(used_)
0407 {
0408 BOOST_BEAST_ASSIGN_EC(ec, error::stale_parser);
0409 return;
0410 }
0411 used_ = true;
0412
0413 m_.result(code);
0414 m_.version(version);
0415 m_.reason(reason);
0416 }
0417
0418 void
0419 on_response_impl(
0420 int, string_view, int,
0421 error_code&, std::false_type)
0422 {
0423 }
0424
0425 void
0426 on_response_impl(
0427 int code,
0428 string_view reason,
0429 int version,
0430 error_code& ec) override
0431 {
0432 this->on_response_impl(
0433 code, reason, version, ec,
0434 std::integral_constant<bool, ! isRequest>{});
0435 }
0436
0437 void
0438 on_field_impl(
0439 field name,
0440 string_view name_string,
0441 string_view value,
0442 error_code& ec) override
0443 {
0444 m_.insert(name, name_string, value, ec);
0445 }
0446
0447 void
0448 on_header_impl(error_code& ec) override
0449 {
0450 ec = {};
0451 }
0452
0453 void
0454 on_body_init_impl(
0455 boost::optional<std::uint64_t> const& content_length,
0456 error_code& ec) override
0457 {
0458 rd_.init(content_length, ec);
0459 rd_inited_ = true;
0460 }
0461
0462 std::size_t
0463 on_body_impl(
0464 string_view body,
0465 error_code& ec) override
0466 {
0467 return rd_.put(net::buffer(
0468 body.data(), body.size()), ec);
0469 }
0470
0471 void
0472 on_chunk_header_impl(
0473 std::uint64_t size,
0474 string_view extensions,
0475 error_code& ec) override
0476 {
0477 if(cb_h_)
0478 return cb_h_(size, extensions, ec);
0479 }
0480
0481 std::size_t
0482 on_chunk_body_impl(
0483 std::uint64_t remain,
0484 string_view body,
0485 error_code& ec) override
0486 {
0487 if(cb_b_)
0488 return cb_b_(remain, body, ec);
0489 return rd_.put(net::buffer(
0490 body.data(), body.size()), ec);
0491 }
0492
0493 void
0494 on_finish_impl(
0495 error_code& ec) override
0496 {
0497 rd_.finish(ec);
0498 }
0499 };
0500
0501 #if BOOST_BEAST_DOXYGEN
0502
0503 template<class Body, class Allocator = std::allocator<char>>
0504 using request_parser = parser<true, Body, Allocator>;
0505
0506
0507 template<class Body, class Allocator = std::allocator<char>>
0508 using response_parser = parser<false, Body, Allocator>;
0509 #endif
0510
0511 }
0512 }
0513 }
0514
0515 #include <boost/beast/http/impl/parser.hpp>
0516
0517 #endif