Line data Source code
1 : //
2 : // Copyright (c) 2025 Vinnie Falco (vinnie dot falco at gmail dot 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 : #include "src/server/detail/pct_decode.hpp"
11 : #include "src/server/detail/route_match.hpp"
12 :
13 : namespace boost {
14 : namespace http {
15 : namespace detail {
16 :
17 116 : router_base::
18 : matcher::
19 : matcher(
20 : std::string_view pat,
21 116 : bool end_arg)
22 116 : : decoded_pat_(
23 0 : [&pat]
24 : {
25 116 : auto s = pct_decode(pat);
26 116 : if( s.size() > 1
27 116 : && s.back() == '/')
28 0 : s.pop_back();
29 116 : return s;
30 232 : }())
31 116 : , end_(end_arg)
32 232 : , slash_(pat == "/")
33 : {
34 116 : if(! slash_)
35 74 : pv_ = grammar::parse(
36 74 : decoded_pat_, detail::path_rule).value();
37 116 : }
38 :
39 : bool
40 82 : router_base::
41 : matcher::
42 : operator()(
43 : route_params_base& p,
44 : match_result& mr) const
45 : {
46 82 : BOOST_ASSERT(! p.path.empty());
47 121 : if( slash_ && (
48 59 : ! end_ ||
49 20 : p.path == "/"))
50 : {
51 : // params = {};
52 39 : mr.adjust_path(p, 0);
53 39 : return true;
54 : }
55 43 : auto it = p.path.data();
56 43 : auto pit = pv_.segs.begin();
57 43 : auto const path_end = it + p.path.size();
58 43 : auto const pend = pv_.segs.end();
59 77 : while(it != path_end && pit != pend)
60 : {
61 : // prefix has to match
62 43 : auto s = core::string_view(it, path_end);
63 43 : if(! p.case_sensitive)
64 : {
65 39 : if(pit->prefix.size() > s.size())
66 9 : return false;
67 37 : s = s.substr(0, pit->prefix.size());
68 : //if(! grammar::ci_is_equal(s, pit->prefix))
69 37 : if(! ci_is_equal(s, pit->prefix))
70 5 : return false;
71 : }
72 : else
73 : {
74 4 : if(! s.starts_with(pit->prefix))
75 2 : return false;
76 : }
77 34 : it += pit->prefix.size();
78 34 : ++pit;
79 : }
80 34 : if(end_)
81 : {
82 : // require full match
83 12 : if( it != path_end ||
84 6 : pit != pend)
85 0 : return false;
86 : }
87 28 : else if(pit != pend)
88 : {
89 0 : return false;
90 : }
91 : // number of matching characters
92 34 : auto const n = it - p.path.data();
93 34 : mr.adjust_path(p, n);
94 34 : return true;
95 : }
96 :
97 : } // detail
98 : } // http
99 : } // boost
|