File indexing completed on 2025-10-31 08:34:26
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