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 % 8 8
Test Date: 2025-12-09 20:49:48 Functions: 100.0 % 4 4

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

Generated by: LCOV version 2.1