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
8 : //
9 :
10 : #ifndef BOOST_HTTP_SRC_SERVER_DETAIL_ROUTER_BASE_HPP
11 : #define BOOST_HTTP_SRC_SERVER_DETAIL_ROUTER_BASE_HPP
12 :
13 : #include <boost/http/server/detail/router_base.hpp>
14 : #include <boost/http/detail/except.hpp>
15 : #include "src/server/detail/route_match.hpp"
16 :
17 : namespace boost {
18 : namespace http {
19 : namespace detail {
20 :
21 : // An entry describes a single route handler.
22 : // This can be an end route or a middleware.
23 : // Members ordered largest-to-smallest for optimal packing.
24 : struct router_base::entry
25 : {
26 : // ~32 bytes (SSO string)
27 : std::string verb_str;
28 :
29 : // 8 bytes each
30 : handler_ptr h;
31 : std::size_t matcher_idx = 0; // flat_router: index into matchers vector
32 :
33 : // 4 bytes
34 : http::method verb = http::method::unknown;
35 :
36 : // 1 byte (+ 3 bytes padding)
37 : bool all;
38 :
39 : // all
40 119 : explicit entry(
41 : handler_ptr h_) noexcept
42 119 : : h(std::move(h_))
43 119 : , all(true)
44 : {
45 119 : }
46 :
47 : // verb match
48 58 : entry(
49 : http::method verb_,
50 : handler_ptr h_) noexcept
51 58 : : h(std::move(h_))
52 58 : , verb(verb_)
53 58 : , all(false)
54 : {
55 58 : BOOST_ASSERT(verb !=
56 : http::method::unknown);
57 58 : }
58 :
59 : // verb match
60 2 : entry(
61 : std::string_view verb_str_,
62 : handler_ptr h_) noexcept
63 2 : : h(std::move(h_))
64 2 : , verb(http::string_to_method(verb_str_))
65 4 : , all(false)
66 : {
67 2 : if(verb != http::method::unknown)
68 0 : return;
69 2 : verb_str = verb_str_;
70 : }
71 :
72 69 : bool match_method(
73 : route_params_base& rp) const noexcept
74 : {
75 69 : detail::route_params_access RP{rp};
76 69 : if(all)
77 9 : return true;
78 60 : if(verb != http::method::unknown)
79 58 : return RP->verb_ == verb;
80 2 : if(RP->verb_ != http::method::unknown)
81 0 : return false;
82 2 : return RP->verb_str_ == verb_str;
83 : }
84 : };
85 :
86 : // A layer is a set of entries that match a route
87 : struct router_base::layer
88 : {
89 : matcher match;
90 : std::vector<entry> entries;
91 :
92 : // middleware layer
93 102 : layer(
94 : std::string_view pat,
95 : handlers hn)
96 102 : : match(pat, false)
97 : {
98 102 : if(match.error())
99 0 : throw_invalid_argument();
100 102 : entries.reserve(hn.n);
101 213 : for(std::size_t i = 0; i < hn.n; ++i)
102 111 : entries.emplace_back(std::move(hn.p[i]));
103 102 : }
104 :
105 : // route layer
106 77 : explicit layer(
107 : std::string_view pat)
108 77 : : match(pat, true)
109 : {
110 77 : if(match.error())
111 12 : throw_invalid_argument();
112 89 : }
113 : };
114 :
115 : struct router_base::impl
116 : {
117 : std::vector<layer> layers;
118 : opt_flags opt;
119 : std::size_t depth_ = 0;
120 :
121 158 : explicit impl(
122 : opt_flags opt_) noexcept
123 158 : : opt(opt_)
124 : {
125 158 : }
126 : };
127 :
128 : } // detail
129 : } // http
130 : } // boost
131 :
132 : #endif
|