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