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

97.1% Lines (33/34) 100.0% Functions (7/7) 81.8% Branches (9/11)
libs/http/src/server/detail/router_base.hpp
Line Branch Hits Source Code
1 //
2 // Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.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 #include <mutex>
17
18 namespace boost {
19 namespace http {
20 namespace detail {
21
22 struct router_base::entry
23 {
24 // ~32 bytes (SSO string)
25 std::string verb_str;
26
27 // 8 bytes each
28 handler_ptr h;
29 std::size_t matcher_idx = 0;
30
31 // 4 bytes
32 http::method verb = http::method::unknown;
33
34 // 1 byte (+ 3 bytes padding)
35 bool all;
36
37 // all methods
38 125 explicit entry(
39 handler_ptr h_) noexcept
40 125 : h(std::move(h_))
41 125 , all(true)
42 {
43 125 }
44
45 // known verb match
46 99 entry(
47 http::method verb_,
48 handler_ptr h_) noexcept
49 99 : h(std::move(h_))
50 99 , verb(verb_)
51 99 , all(false)
52 {
53
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 99 times.
99 BOOST_ASSERT(verb !=
54 http::method::unknown);
55 99 }
56
57 // string verb match
58 3 entry(
59 std::string_view verb_str_,
60 handler_ptr h_) noexcept
61 3 : h(std::move(h_))
62 3 , verb(http::string_to_method(verb_str_))
63 6 , all(false)
64 {
65
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if(verb != http::method::unknown)
66 return;
67 3 verb_str = verb_str_;
68 }
69
70 130 bool match_method(
71 route_params& rp) const noexcept
72 {
73 130 route_params_access RP{rp};
74
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 120 times.
130 if(all)
75 10 return true;
76
2/2
✓ Branch 0 taken 117 times.
✓ Branch 1 taken 3 times.
120 if(verb != http::method::unknown)
77 117 return RP->verb_ == verb;
78
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 2 times.
3 if(RP->verb_ != http::method::unknown)
79 1 return false;
80 2 return RP->verb_str_ == verb_str;
81 }
82 };
83
84 struct router_base::impl
85 {
86 std::vector<entry> entries;
87 std::vector<matcher> matchers;
88
89 std::size_t pending_route_ = SIZE_MAX;
90 mutable std::once_flag finalized_;
91
92 options_handler_ptr options_handler_;
93 std::uint64_t global_methods_ = 0;
94 std::vector<std::string> global_custom_verbs_;
95 std::string global_allow_header_;
96
97 opt_flags opt_;
98 std::size_t depth_ = 0;
99
100 222 explicit impl(
101 opt_flags opt) noexcept
102 222 : opt_(opt)
103 {
104 222 }
105
106 void finalize_pending();
107
108 // Thread-safe lazy finalization for dispatch
109 206 void ensure_finalized() const
110 {
111
1/1
✓ Branch 1 taken 206 times.
206 std::call_once(finalized_, [this]() {
112 148 const_cast<impl*>(this)->finalize_pending();
113 148 });
114 206 }
115
116 void update_allow_for_entry(
117 matcher& m,
118 entry const& e);
119
120 void rebuild_global_allow_header();
121
122 route_task
123 dispatch_loop(
124 route_params& p,
125 bool is_options) const;
126
127 static std::string
128 build_allow_header(
129 std::uint64_t methods,
130 std::vector<std::string> const& custom);
131
132 static opt_flags
133 compute_effective_opts(
134 opt_flags parent,
135 opt_flags child);
136
137 static void
138 restore_path(
139 route_params& p,
140 std::size_t base_len);
141 };
142
143 } // detail
144 } // http
145 } // boost
146
147 #endif
148