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