LCOV - code coverage report
Current view: top level - boost/http_proto/server - router_types.hpp (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 100.0 % 10 10
Test Date: 2025-12-30 20:59:33 Functions: 100.0 % 5 5

            Line data    Source code
       1              : //
       2              : // Copyright (c) 2025 Vinnie Falco (vinnie dot falco at gmail dot com)
       3              : //
       4              : // Distributed under the Boost Software License, Version 1.0. (See accompanying
       5              : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
       6              : //
       7              : // Official repository: https://github.com/cppalliance/http_proto
       8              : //
       9              : 
      10              : #ifndef BOOST_HTTP_PROTO_SERVER_ROUTER_TYPES_HPP
      11              : #define BOOST_HTTP_PROTO_SERVER_ROUTER_TYPES_HPP
      12              : 
      13              : #include <boost/http_proto/detail/config.hpp>
      14              : #include <boost/http_proto/method.hpp>
      15              : #include <boost/http_proto/detail/except.hpp>
      16              : #include <boost/core/detail/string_view.hpp>
      17              : #include <boost/system/error_code.hpp>
      18              : #include <exception>
      19              : #include <string>
      20              : #include <type_traits>
      21              : 
      22              : namespace boost {
      23              : namespace http_proto {
      24              : 
      25              : /** The result type returned by a route handler.
      26              : 
      27              :     Route handlers use this type to report errors that prevent
      28              :     normal processing. A handler must never return a non-failing
      29              :     (i.e. `ec.failed() == false`) value. Returning a default-constructed
      30              :     `system::error_code` is disallowed; handlers that complete
      31              :     successfully must instead return a valid @ref route result.
      32              : */
      33              : using route_result = system::error_code;
      34              : 
      35              : /** Route handler return values
      36              : 
      37              :     These values determine how the caller proceeds after invoking
      38              :     a route handler. Each enumerator represents a distinct control
      39              :     action�whether the request was handled, should continue to the
      40              :     next route, transfers ownership of the session, or signals that
      41              :     the connection should be closed.
      42              : */
      43              : enum class route
      44              : {
      45              :     /** The handler requests that the connection be closed.
      46              : 
      47              :         No further requests will be processed. The caller should
      48              :         close the connection once the current response, if any,
      49              :         has been sent.
      50              :     */
      51              :     close = 1,
      52              : 
      53              :     /** The handler completed the request.
      54              : 
      55              :         The response has been fully transmitted, and no further
      56              :         handlers or routes will be invoked. The caller should continue
      57              :         by either reading the next request on a persistent connection
      58              :         or closing the session if it is not keep-alive.
      59              :     */
      60              :     complete,
      61              : 
      62              :     /** The handler is suspending the route.
      63              : 
      64              :         When the handler returns this value, the router is placed into
      65              :         a suspended state which can later be reactivated by invoking
      66              :         @ref basic_router::resume. Depending on the implementation,
      67              :         this might detach the handler from the session until it is
      68              :         resumed.
      69              :     */
      70              :     suspend,
      71              : 
      72              :     /** The handler declined to process the request.
      73              : 
      74              :         The handler chose not to generate a response. The caller
      75              :         continues invoking the remaining handlers in the same route
      76              :         until one returns @ref send. If none do, the caller proceeds
      77              :         to evaluate the next matching route.
      78              : 
      79              :         This value is returned by @ref basic_router::dispatch if no
      80              :         handlers in any route handle the request.
      81              :     */
      82              :     next,
      83              : 
      84              :     /** The handler declined the current route.
      85              : 
      86              :         The handler wishes to skip any remaining handlers in the
      87              :         current route and move on to the next matching route. The
      88              :         caller stops invoking handlers in this route and resumes
      89              :         evaluation with the next candidate route.
      90              :     */
      91              :     next_route,
      92              : 
      93              :     /** The request was handled.
      94              : 
      95              :         The route handler processed the request and prepared
      96              :         the response serializer. The caller will send the response
      97              :         before reading the next request or closing the connection.
      98              :     */
      99              :     send
     100              : };
     101              : 
     102              : //------------------------------------------------
     103              : 
     104              : } // http_proto
     105              : namespace system {
     106              : template<>
     107              : struct is_error_code_enum<
     108              :     ::boost::http_proto::route>
     109              : {
     110              :     static bool const value = true;
     111              : };
     112              : } // system
     113              : namespace http_proto {
     114              : 
     115              : namespace detail {
     116              : struct BOOST_HTTP_PROTO_SYMBOL_VISIBLE route_cat_type
     117              :     : system::error_category
     118              : {
     119              :     BOOST_HTTP_PROTO_DECL const char* name() const noexcept override;
     120              :     BOOST_HTTP_PROTO_DECL std::string message(int) const override;
     121              :     BOOST_HTTP_PROTO_DECL char const* message(
     122              :         int, char*, std::size_t) const noexcept override;
     123           43 :     BOOST_SYSTEM_CONSTEXPR route_cat_type()
     124           43 :         : error_category(0x51c90d393754ecdf )
     125              :     {
     126           43 :     }
     127              : };
     128              : BOOST_HTTP_PROTO_DECL extern route_cat_type route_cat;
     129              : } // detail
     130              : 
     131              : inline
     132              : BOOST_SYSTEM_CONSTEXPR
     133              : system::error_code
     134         2357 : make_error_code(route ev) noexcept
     135              : {
     136              :     return system::error_code{static_cast<
     137              :         std::underlying_type<route>::type>(ev),
     138         2357 :         detail::route_cat};
     139              : }
     140              : 
     141              : /** Return true if `rv` is a route result.
     142              : 
     143              :     A @ref route_result can hold any error code,
     144              :     and this function returns `true` only if `rv`
     145              :     holds a value from the @ref route enumeration.
     146              : */
     147          223 : inline bool is_route_result(
     148              :     route_result rv) noexcept
     149              : {
     150          223 :     return &rv.category() == &detail::route_cat;
     151              : }
     152              : 
     153              : //------------------------------------------------
     154              : 
     155              : class resumer;
     156              : 
     157              : /** Function to suspend a route handler from its session
     158              : 
     159              :     This holds an reference to an implementation
     160              :     which suspends the router which dispatched the handler.
     161              : */
     162              : class suspender
     163              : {
     164              : public:
     165              :     /** Base class of the implementation
     166              :     */
     167              :     struct BOOST_HTTP_PROTO_SYMBOL_VISIBLE
     168              :         owner
     169              :     {
     170              :         BOOST_HTTP_PROTO_DECL
     171              :         virtual resumer do_suspend();
     172              :         virtual void do_resume(route_result const&) = 0;
     173              :         virtual void do_resume(std::exception_ptr) = 0;
     174              :     };
     175              : 
     176            1 :     suspender() = default;
     177              :     suspender(suspender const&) = default;
     178              :     suspender& operator=(suspender const&) = default;
     179              : 
     180              :     explicit
     181              :     suspender(
     182              :         owner& who) noexcept
     183              :         : p_(&who)
     184              :     {
     185              :     }
     186              : 
     187              :     /** Suspend and invoke the given function
     188              : 
     189              :         The function will be invoked with this equivalent signature:
     190              :         @code
     191              :         void( resumer );
     192              :         @endcode
     193              : 
     194              :         @return A @ref route_result equal to @ref route::suspend
     195              :     */
     196              :     template<class F>
     197              :     route_result    
     198              :     operator()(F&& f);
     199              : 
     200              : private:
     201              :     friend resumer;
     202              :     // Clang doesn't consider uninstantiated templates
     203              :     // when checking for unused private fields.
     204              :     owner* p_
     205              :     #if defined(__clang__)
     206              :         __attribute__((unused))
     207              :     #endif
     208              :         = nullptr; 
     209              : };
     210              : 
     211              : //------------------------------------------------
     212              : 
     213              : /** Function to resume a suspended route.
     214              : 
     215              :     This holds a reference to an implementation which resumes the handler's
     216              :     session. The resume function is typically obtained at the time the
     217              :     route is suspended.
     218              : */
     219              : class resumer
     220              : {
     221              : public:
     222              :     /** Constructor
     223              : 
     224              :         Default constructed resume functions will
     225              :         be empty. An exception is thrown when
     226              :         attempting to invoke an empty object.
     227              :     */
     228              :     resumer() = default;
     229              : 
     230              :     /** Constructor
     231              : 
     232              :         Copies of resume functions behave the same
     233              :         as the original
     234              :     */
     235              :     resumer(resumer const&) = default;
     236              : 
     237              :     /** Assignment
     238              : 
     239              :         Copies of resume functions behave the same
     240              :         as the original
     241              :     */
     242              :     resumer& operator=(resumer const&) = default;
     243              : 
     244              :     /** Constructor
     245              :     */
     246              :     explicit
     247              :     resumer(
     248              :         suspender::owner& who) noexcept
     249              :         : p_(&who)
     250              :     {
     251              :     }
     252              : 
     253              :     /** Resume the session
     254              : 
     255              :         When a session is resumed, routing continues as if the handler
     256              :         had returned the @ref route_result contained in @p rv.
     257              : 
     258              :         @param rv The route result to resume with.
     259              : 
     260              :         @throw std::invalid_argument If the object is empty.
     261              :     */
     262              :     void operator()(
     263              :         route_result const& rv) const
     264              :     {
     265              :         if(! p_)
     266              :             detail::throw_invalid_argument();
     267              :         p_->do_resume(rv);
     268              :     }
     269              : 
     270              :     /** Resume the session with an exception
     271              : 
     272              :         When a session is resumed with an exception, the exception
     273              :         is propagated through the router's error handling mechanism.
     274              : 
     275              :         @param ep The exception to propagate.
     276              : 
     277              :         @throw std::invalid_argument If the object is empty.
     278              :     */
     279              :     void operator()(
     280              :         std::exception_ptr ep) const
     281              :     {
     282              :         if(! p_)
     283              :             detail::throw_invalid_argument();
     284              :         p_->do_resume(ep);
     285              :     }
     286              : 
     287              : private:
     288              :     suspender::owner* p_
     289              :     #if defined(__clang__)
     290              :         __attribute__((unused))
     291              :     #endif
     292              :         = nullptr; 
     293              : };
     294              : 
     295              : template<class F>
     296              : auto    
     297              : suspender::
     298              : operator()(F&& f) ->
     299              :     route_result
     300              : {
     301              :     if(! p_)
     302              :         detail::throw_logic_error();
     303              :     std::forward<F>(f)(p_->do_suspend());
     304              :     return route::suspend;
     305              : }
     306              : 
     307              : //------------------------------------------------
     308              : 
     309              : namespace detail {
     310              : class any_router;
     311              : } // detail
     312              : template<class>
     313              : class basic_router;
     314              : 
     315              : /** Base class for request objects
     316              : 
     317              :     This is a required public base for any `Request`
     318              :     type used with @ref basic_router.
     319              : */
     320              : class route_params_base
     321              : {
     322              : public:
     323              :     /** Return true if the request method matches `m`
     324              :     */
     325            2 :     bool is_method(
     326              :         http_proto::method m) const noexcept
     327              :     {
     328            2 :         return verb_ == m;
     329              :     }
     330              : 
     331              :     /** Return true if the request method matches `s`
     332              :     */
     333              :     BOOST_HTTP_PROTO_DECL
     334              :     bool is_method(
     335              :         core::string_view s) const noexcept;
     336              : 
     337              :     /** The mount path of the current router
     338              : 
     339              :         This is the portion of the request path
     340              :         which was matched to select the handler.
     341              :         The remaining portion is available in
     342              :         @ref path.
     343              :     */
     344              :     core::string_view base_path;
     345              : 
     346              :     /** The current pathname, relative to the base path
     347              :     */
     348              :     core::string_view path;
     349              : 
     350              : private:
     351              :     friend class /*detail::*/any_router;
     352              :     template<class>
     353              :     friend class basic_router;
     354              :     struct match_result;
     355              :     route_params_base& operator=(
     356              :         route_params_base const&) = delete;
     357              : 
     358              :     std::string verb_str_;
     359              :     std::string decoded_path_;
     360              :     system::error_code ec_;
     361              :     std::exception_ptr ep_;
     362              :     std::size_t pos_ = 0;
     363              :     std::size_t resume_ = 0;
     364              :     http_proto::method verb_ =
     365              :         http_proto::method::unknown;
     366              :     bool addedSlash_ = false;
     367              :     bool case_sensitive = false;
     368              :     bool strict = false;
     369              : };
     370              : 
     371              : } // http_proto
     372              : } // boost
     373              : 
     374              : #endif
        

Generated by: LCOV version 2.1