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  
#include "src/server/detail/pct_decode.hpp"
10  
#include "src/server/detail/pct_decode.hpp"
11  
#include "src/server/detail/route_match.hpp"
11  
#include "src/server/detail/route_match.hpp"
12  

12  

13  
namespace boost {
13  
namespace boost {
14  
namespace http {
14  
namespace http {
15  

15  

16  
detail::router_base::
16  
detail::router_base::
17  
matcher::
17  
matcher::
18  
matcher(
18  
matcher(
19  
    std::string_view pat,
19  
    std::string_view pat,
20  
    bool end_arg)
20  
    bool end_arg)
21  
    : decoded_pat_(
21  
    : decoded_pat_(
22  
        [&pat]
22  
        [&pat]
23  
        {
23  
        {
24  
            auto s = detail::pct_decode(pat);
24  
            auto s = detail::pct_decode(pat);
25  
            if( s.size() > 1
25  
            if( s.size() > 1
26  
                && s.back() == '/')
26  
                && s.back() == '/')
27  
                s.pop_back();
27  
                s.pop_back();
28  
            return s;
28  
            return s;
29  
        }())
29  
        }())
30  
    , end_(end_arg)
30  
    , end_(end_arg)
31  
    , slash_(pat == "/")
31  
    , slash_(pat == "/")
32  
{
32  
{
33  
    if(! slash_)
33  
    if(! slash_)
34  
    {
34  
    {
35  
        auto rv = parse_route_pattern(decoded_pat_);
35  
        auto rv = parse_route_pattern(decoded_pat_);
36  
        if(rv.has_error())
36  
        if(rv.has_error())
37  
            ec_ = rv.error();
37  
            ec_ = rv.error();
38  
        else
38  
        else
39  
            pattern_ = std::move(rv.value());
39  
            pattern_ = std::move(rv.value());
40  
    }
40  
    }
41  
}
41  
}
42  

42  

43  
bool
43  
bool
44  
detail::router_base::
44  
detail::router_base::
45  
matcher::
45  
matcher::
46  
operator()(
46  
operator()(
47  
    route_params& p,
47  
    route_params& p,
48  
    match_result& mr) const
48  
    match_result& mr) const
49  
{
49  
{
50  
    BOOST_ASSERT(! p.path.empty());
50  
    BOOST_ASSERT(! p.path.empty());
51  

51  

52  
    // Root pattern special case
52  
    // Root pattern special case
53  
    if(slash_ && (!end_ || p.path == "/"))
53  
    if(slash_ && (!end_ || p.path == "/"))
54  
    {
54  
    {
55  
        mr.adjust_path(p, 0);
55  
        mr.adjust_path(p, 0);
56  
        return true;
56  
        return true;
57  
    }
57  
    }
58  

58  

59  
    // Convert bitflags to match_options
59  
    // Convert bitflags to match_options
60  
    auto& pv = *detail::route_params_access{p};
60  
    auto& pv = *detail::route_params_access{p};
61  
    detail::match_options opts{
61  
    detail::match_options opts{
62  
        pv.case_sensitive,
62  
        pv.case_sensitive,
63  
        pv.strict,
63  
        pv.strict,
64  
        end_
64  
        end_
65  
    };
65  
    };
66  

66  

67  
    auto rv = match_route(p.path, pattern_, opts);
67  
    auto rv = match_route(p.path, pattern_, opts);
68  
    if(rv.has_error())
68  
    if(rv.has_error())
69  
        return false;
69  
        return false;
70  

70  

71  
    auto const n = rv->matched_length;
71  
    auto const n = rv->matched_length;
72  
    mr.adjust_path(p, n);
72  
    mr.adjust_path(p, n);
73  
    mr.params_ = std::move(rv->params);
73  
    mr.params_ = std::move(rv->params);
74  
    return true;
74  
    return true;
75  
}
75  
}
76  

76  

77  
} // http
77  
} // http
78  
} // boost
78  
} // boost