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_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 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 3 : if(verb != http::method::unknown)
66 0 : 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 130 : if(all)
75 10 : return true;
76 120 : if(verb != http::method::unknown)
77 117 : return RP->verb_ == verb;
78 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 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
|