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 -
    explicit entry(
 
39 -
        handler_ptr h_) noexcept
 
40 -
        : h(std::move(h_))
 
41 -
        , all(true)
 
42 -
    {
 
43 -
    }
 
44 -

 
45 -
    // known verb match
 
46 -
    entry(
 
47 -
        http::method verb_,
 
48 -
        handler_ptr h_) noexcept
 
49 -
        : h(std::move(h_))
 
50 -
        , verb(verb_)
 
51 -
        , all(false)
 
52 -
    {
 
53 -
        BOOST_ASSERT(verb !=
 
54 -
            http::method::unknown);
 
55 -
    }
 
56 -

 
57 -
    // string verb match
 
58 -
    entry(
 
59 -
        std::string_view verb_str_,
 
60 -
        handler_ptr h_) noexcept
 
61 -
        : h(std::move(h_))
 
62 -
        , verb(http::string_to_method(verb_str_))
 
63 -
        , all(false)
 
64 -
    {
 
65 -
        if(verb != http::method::unknown)
 
66 -
            return;
 
67 -
        verb_str = verb_str_;
 
68 -
    }
 
69 -

 
70 -
    bool match_method(
 
71 -
        route_params& rp) const noexcept
 
72 -
    {
 
73 -
        route_params_access RP{rp};
 
74 -
        if(all)
 
75 -
            return true;
 
76 -
        if(verb != http::method::unknown)
 
77 -
            return RP->verb_ == verb;
 
78 -
        if(RP->verb_ != http::method::unknown)
 
79 -
            return false;
 
80 -
        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 -
    explicit impl(
 
101 -
        opt_flags opt) noexcept
 
102 -
        : opt_(opt)
 
103 -
    {
 
104 -
    }
 
105 -

 
106 -
    void finalize_pending();
 
107 -

 
108 -
    // Thread-safe lazy finalization for dispatch
 
109 -
    void ensure_finalized() const
 
110 -
    {
 
111 -
        std::call_once(finalized_, [this]() {
 
112 -
            const_cast<impl*>(this)->finalize_pending();
 
113 -
        });
 
114 -
    }
 
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