TLA Line data 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_ANY_ROUTER_HPP
11 : #define BOOST_HTTP_SRC_SERVER_DETAIL_ANY_ROUTER_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 HIT 82 : explicit entry(
39 : handler_ptr h_) noexcept
40 82 : : h(std::move(h_))
41 82 : , all(true)
42 : {
43 82 : }
44 :
45 : // known verb match
46 58 : entry(
47 : http::method verb_,
48 : handler_ptr h_) noexcept
49 58 : : h(std::move(h_))
50 58 : , verb(verb_)
51 58 : , all(false)
52 : {
53 58 : BOOST_ASSERT(verb !=
54 : http::method::unknown);
55 58 : }
56 :
57 : // string verb match
58 2 : entry(
59 : std::string_view verb_str_,
60 : handler_ptr h_) noexcept
61 2 : : h(std::move(h_))
62 2 : , verb(http::string_to_method(verb_str_))
63 4 : , all(false)
64 : {
65 2 : if(verb != http::method::unknown)
66 MIS 0 : return;
67 HIT 2 : verb_str = verb_str_;
68 : }
69 :
70 69 : bool match_method(
71 : route_params& rp) const noexcept
72 : {
73 69 : route_params_access RP{rp};
74 69 : if(all)
75 9 : return true;
76 60 : if(verb != http::method::unknown)
77 58 : return RP->verb_ == verb;
78 2 : if(RP->verb_ != http::method::unknown)
79 MIS 0 : return false;
80 HIT 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 168 : explicit impl(
101 : opt_flags opt) noexcept
102 168 : : opt_(opt)
103 : {
104 168 : }
105 :
106 : void finalize_pending();
107 :
108 : // Thread-safe lazy finalization for dispatch
109 113 : void ensure_finalized() const
110 : {
111 113 : std::call_once(finalized_, [this]() {
112 99 : const_cast<impl*>(this)->finalize_pending();
113 99 : });
114 113 : }
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
|