libs/http/src/server/detail/router_base.hpp

92.9% Lines (39/42) 100.0% Functions (7/7) 77.8% Branches (14/18)
libs/http/src/server/detail/router_base.hpp
Line Branch Hits 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
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
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
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if(verb != http::method::unknown)
68 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
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 60 times.
69 if(all)
77 9 return true;
78
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 2 times.
60 if(verb != http::method::unknown)
79 58 return RP->verb_ == verb;
80
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if(RP->verb_ != http::method::unknown)
81 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
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 102 times.
102 if(match.error())
99 throw_invalid_argument();
100
1/1
✓ Branch 1 taken 102 times.
102 entries.reserve(hn.n);
101
2/2
✓ Branch 0 taken 111 times.
✓ Branch 1 taken 102 times.
213 for(std::size_t i = 0; i < hn.n; ++i)
102
1/1
✓ Branch 2 taken 111 times.
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
2/2
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 65 times.
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
133