1  
//
1  
//
2  
// Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com)
2  
// Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com)
3  
//
3  
//
4  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
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)
5  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6  
//
6  
//
7  
// Official repository: https://github.com/cppalliance/http
7  
// Official repository: https://github.com/cppalliance/http
8  
//
8  
//
9  

9  

10  
#ifndef BOOST_HTTP_SERVER_DETAIL_ROUTER_BASE_HPP
10  
#ifndef BOOST_HTTP_SERVER_DETAIL_ROUTER_BASE_HPP
11  
#define BOOST_HTTP_SERVER_DETAIL_ROUTER_BASE_HPP
11  
#define BOOST_HTTP_SERVER_DETAIL_ROUTER_BASE_HPP
12  

12  

13  
#include <boost/http/detail/config.hpp>
13  
#include <boost/http/detail/config.hpp>
14  
#include <boost/http/server/route_handler.hpp>
14  
#include <boost/http/server/route_handler.hpp>
15  
#include <boost/http/method.hpp>
15  
#include <boost/http/method.hpp>
16  
#include <boost/url/url_view.hpp>
16  
#include <boost/url/url_view.hpp>
17  
#include <boost/mp11/algorithm.hpp>
17  
#include <boost/mp11/algorithm.hpp>
18  
#include <boost/assert.hpp>
18  
#include <boost/assert.hpp>
19  
#include <exception>
19  
#include <exception>
20  
#include <memory>
20  
#include <memory>
21  
#include <string_view>
21  
#include <string_view>
22  
#include <type_traits>
22  
#include <type_traits>
23  

23  

24  
namespace boost {
24  
namespace boost {
25  
namespace http {
25  
namespace http {
26  
namespace detail {
26  
namespace detail {
27  

27  

28  
template<class> class router;
28  
template<class> class router;
29  

29  

30  
/** Non-template base class for all routers.
30  
/** Non-template base class for all routers.
31  

31  

32  
    Holds a shared reference to an internal routing table
32  
    Holds a shared reference to an internal routing table
33  
    that is built incrementally as routes are added. The routing
33  
    that is built incrementally as routes are added. The routing
34  
    table uses contiguous flat arrays for cache-friendly dispatch.
34  
    table uses contiguous flat arrays for cache-friendly dispatch.
35  

35  

36  
    Copies share the same underlying routing data. Modifying
36  
    Copies share the same underlying routing data. Modifying
37  
    a router after it has been copied is not permitted and
37  
    a router after it has been copied is not permitted and
38  
    results in undefined behavior.
38  
    results in undefined behavior.
39  

39  

40  
    @par Thread Safety
40  
    @par Thread Safety
41  

41  

42  
    `dispatch` may be called concurrently on routers that share
42  
    `dispatch` may be called concurrently on routers that share
43  
    the same data. Modification through `router` is not
43  
    the same data. Modification through `router` is not
44  
    thread-safe and must not be performed concurrently with any
44  
    thread-safe and must not be performed concurrently with any
45  
    other operation.
45  
    other operation.
46  

46  

47  
    @see router
47  
    @see router
48  
*/
48  
*/
49  
class BOOST_HTTP_DECL
49  
class BOOST_HTTP_DECL
50  
    router_base
50  
    router_base
51  
{
51  
{
52  
    struct impl;
52  
    struct impl;
53  
    std::shared_ptr<impl> impl_;
53  
    std::shared_ptr<impl> impl_;
54  

54  

55  
    template<class, class> friend class http::router;
55  
    template<class, class> friend class http::router;
56  

56  

57  
protected:
57  
protected:
58  
    using opt_flags = unsigned int;
58  
    using opt_flags = unsigned int;
59  

59  

60  
    enum
60  
    enum
61  
    {
61  
    {
62  
        is_invalid = 0,
62  
        is_invalid = 0,
63  
        is_plain = 1,
63  
        is_plain = 1,
64  
        is_error = 2,
64  
        is_error = 2,
65  
        is_exception = 8
65  
        is_exception = 8
66  
    };
66  
    };
67  

67  

68  
    struct BOOST_HTTP_DECL
68  
    struct BOOST_HTTP_DECL
69  
        handler
69  
        handler
70  
    {
70  
    {
71  
        char const kind;
71  
        char const kind;
72  
        explicit handler(char kind_) noexcept : kind(kind_) {}
72  
        explicit handler(char kind_) noexcept : kind(kind_) {}
73  
        virtual ~handler() = default;
73  
        virtual ~handler() = default;
74  
        virtual auto invoke(route_params&) const ->
74  
        virtual auto invoke(route_params&) const ->
75  
            route_task = 0;
75  
            route_task = 0;
76  
    };
76  
    };
77  

77  

78  
    using handler_ptr = std::unique_ptr<handler>;
78  
    using handler_ptr = std::unique_ptr<handler>;
79  

79  

80  
    struct handlers
80  
    struct handlers
81  
    {
81  
    {
82  
        std::size_t n;
82  
        std::size_t n;
83  
        handler_ptr* p;
83  
        handler_ptr* p;
84  
    };
84  
    };
85  

85  

86  
    struct BOOST_HTTP_DECL
86  
    struct BOOST_HTTP_DECL
87  
        options_handler
87  
        options_handler
88  
    {
88  
    {
89  
        virtual ~options_handler() = default;
89  
        virtual ~options_handler() = default;
90  
        virtual route_task invoke(
90  
        virtual route_task invoke(
91  
            route_params&,
91  
            route_params&,
92  
            std::string_view allow) const = 0;
92  
            std::string_view allow) const = 0;
93  
    };
93  
    };
94  

94  

95  
    using options_handler_ptr = std::unique_ptr<options_handler>;
95  
    using options_handler_ptr = std::unique_ptr<options_handler>;
96  

96  

97  
protected:
97  
protected:
98  
    using match_result = route_params::match_result;
98  
    using match_result = route_params::match_result;
99  
    struct matcher;
99  
    struct matcher;
100  
    struct entry;
100  
    struct entry;
101  

101  

102  
    // Construct with options
102  
    // Construct with options
103  
    explicit router_base(opt_flags);
103  
    explicit router_base(opt_flags);
104  

104  

105  
    // Registration helpers
105  
    // Registration helpers
106  
    void add_middleware(std::string_view pattern, handlers hn);
106  
    void add_middleware(std::string_view pattern, handlers hn);
107  
    void inline_router(std::string_view pattern, router_base&& sub);
107  
    void inline_router(std::string_view pattern, router_base&& sub);
108  
    std::size_t new_route(std::string_view pattern);
108  
    std::size_t new_route(std::string_view pattern);
109  
    void add_to_route(std::size_t idx, http::method verb, handlers hn);
109  
    void add_to_route(std::size_t idx, http::method verb, handlers hn);
110  
    void add_to_route(std::size_t idx, std::string_view verb, handlers hn);
110  
    void add_to_route(std::size_t idx, std::string_view verb, handlers hn);
111  
    void finalize_pending();
111  
    void finalize_pending();
112  
    void set_options_handler_impl(options_handler_ptr p);
112  
    void set_options_handler_impl(options_handler_ptr p);
113  

113  

114  
public:
114  
public:
115  
    /** Default constructor.
115  
    /** Default constructor.
116  

116  

117  
        Creates a router in an empty state. The only valid
117  
        Creates a router in an empty state. The only valid
118  
        operations on a default-constructed router are
118  
        operations on a default-constructed router are
119  
        assignment, destruction, and copying.
119  
        assignment, destruction, and copying.
120  
    */
120  
    */
121  
    router_base() = default;
121  
    router_base() = default;
122  

122  

123  
    router_base(router_base const&) = default;
123  
    router_base(router_base const&) = default;
124  
    router_base(router_base&&) noexcept = default;
124  
    router_base(router_base&&) noexcept = default;
125  
    router_base& operator=(router_base const&) = default;
125  
    router_base& operator=(router_base const&) = default;
126  
    router_base& operator=(router_base&&) noexcept = default;
126  
    router_base& operator=(router_base&&) noexcept = default;
127  
    ~router_base() = default;
127  
    ~router_base() = default;
128  

128  

129  
    /** Dispatch a request using a known HTTP method.
129  
    /** Dispatch a request using a known HTTP method.
130  

130  

131  
        @param verb The HTTP method to match. Must not be
131  
        @param verb The HTTP method to match. Must not be
132  
        @ref http::method::unknown.
132  
        @ref http::method::unknown.
133  

133  

134  
        @param url The full request target used for route matching.
134  
        @param url The full request target used for route matching.
135  

135  

136  
        @param p The params to pass to handlers.
136  
        @param p The params to pass to handlers.
137  

137  

138  
        @return A task yielding the @ref route_result describing
138  
        @return A task yielding the @ref route_result describing
139  
        how routing completed.
139  
        how routing completed.
140  

140  

141  
        @throws std::invalid_argument If @p verb is
141  
        @throws std::invalid_argument If @p verb is
142  
        @ref http::method::unknown.
142  
        @ref http::method::unknown.
143  
    */
143  
    */
144  
    route_task
144  
    route_task
145  
    dispatch(
145  
    dispatch(
146  
        http::method verb,
146  
        http::method verb,
147  
        urls::url_view const& url,
147  
        urls::url_view const& url,
148  
        route_params& p) const;
148  
        route_params& p) const;
149  

149  

150  
    /** Dispatch a request using a method string.
150  
    /** Dispatch a request using a method string.
151  

151  

152  
        @param verb The HTTP method string to match. Must not be empty.
152  
        @param verb The HTTP method string to match. Must not be empty.
153  

153  

154  
        @param url The full request target used for route matching.
154  
        @param url The full request target used for route matching.
155  

155  

156  
        @param p The params to pass to handlers.
156  
        @param p The params to pass to handlers.
157  

157  

158  
        @return A task yielding the @ref route_result describing
158  
        @return A task yielding the @ref route_result describing
159  
        how routing completed.
159  
        how routing completed.
160  

160  

161  
        @throws std::invalid_argument If @p verb is empty.
161  
        @throws std::invalid_argument If @p verb is empty.
162  
    */
162  
    */
163  
    route_task
163  
    route_task
164  
    dispatch(
164  
    dispatch(
165  
        std::string_view verb,
165  
        std::string_view verb,
166  
        urls::url_view const& url,
166  
        urls::url_view const& url,
167  
        route_params& p) const;
167  
        route_params& p) const;
168  

168  

169  
    /** Maximum nesting depth for routers.
169  
    /** Maximum nesting depth for routers.
170  

170  

171  
        This limit applies to nested routers added via use().
171  
        This limit applies to nested routers added via use().
172  
        Exceeding this limit throws std::length_error at
172  
        Exceeding this limit throws std::length_error at
173  
        insertion time.
173  
        insertion time.
174  
    */
174  
    */
175  
    static constexpr std::size_t max_path_depth = 16;
175  
    static constexpr std::size_t max_path_depth = 16;
176  
};
176  
};
177  

177  

178  
} // detail
178  
} // detail
179  
} // http
179  
} // http
180  
} // boost
180  
} // boost
181  

181  

182  
#endif
182  
#endif