• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

PowerDNS / pdns / 8288098529

14 Mar 2024 03:46PM UTC coverage: 50.952% (-8.3%) from 59.235%
8288098529

push

github

web-flow
Merge pull request #13916 from Habbie/dockerignore

.dockerignore: adjust for https://github.com/docker/buildx/issues/850

11119 of 34886 branches covered (31.87%)

Branch coverage included in aggregate %.

43698 of 72700 relevant lines covered (60.11%)

125648.32 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/ext/yahttp/yahttp/router.cpp
1
/* @file
2
 * @brief Concrete implementation of Router 
3
 */
4
#include "yahttp.hpp"
5
#include "router.hpp"
6

7
namespace YaHTTP {
8
  // router is defined here.
9
  YaHTTP::Router Router::router;
10

11
  void Router::map(const std::string& method, const std::string& url, THandlerFunction handler, const std::string& name) {
12
    std::string method2 = method;
13
    bool isopen=false;
×
14
    // add into vector
×
15
    for(std::string::const_iterator i = url.begin(); i != url.end(); i++) {
×
16
       if (*i == '<' && isopen) throw Error("Invalid URL mask, cannot have < after <");
17
       if (*i == '<') isopen = true;
×
18
       if (*i == '>' && !isopen) throw Error("Invalid URL mask, cannot have > without < first");
×
19
       if (*i == '>') isopen = false;
×
20
    }
×
21
    std::transform(method2.begin(), method2.end(), method2.begin(), ::toupper); 
×
22
    routes.push_back(funcptr::make_tuple(method2, url, handler, name));
×
23
  };
×
24

×
25
  bool Router::match(const std::string& route, const URL& requrl, std::map<std::string, TDelim> &params) {
×
26
     size_t rpos = 0;
27
     size_t upos = 0;
×
28
     size_t npos = 0;
×
29
     size_t nstart = 0;
×
30
     size_t nend = 0;
×
31
     std::string pname;
×
32
     for(; rpos < route.size() && upos < requrl.path.size(); ) {
33
        if (route[rpos] == '<') {
34
          nstart = upos;
×
35
          npos = rpos+1;
×
36
          // start of parameter
×
37
          while(rpos < route.size() && route[rpos] != '>') {
×
38
            rpos++;
×
39
          }
40
          pname = std::string(route.begin()+static_cast<long>(npos), route.begin()+static_cast<long>(rpos));
×
41
          // then we also look it on the url
42
          if (pname[0] == '*') {
×
43
            pname = pname.substr(1);
44
            // this matches whatever comes after it, basically end of string
×
45
            nend = requrl.path.size();
×
46
            if (!pname.empty()) {
×
47
              params[pname] = funcptr::tie(nstart,nend);
×
48
            }
49
            rpos = route.size();
×
50
            upos = requrl.path.size();
×
51
            break;
52
          } else { 
×
53
            // match until url[upos] or next / if pattern is at end
×
54
            while (upos < requrl.path.size()) {
55
               if (route[rpos+1] == '\0' && requrl.path[upos] == '/') {
×
56
                  break;
×
57
               }
×
58
               if (requrl.path[upos] == route[rpos+1]) {
×
59
                  break;
×
60
               }
×
61
               upos++;
×
62
            }
63
            nend = upos;
×
64
            params[pname] = funcptr::tie(nstart, nend);
×
65
          }
×
66
          upos--;
×
67
        }
×
68
        else if (route[rpos] != requrl.path[upos]) {
×
69
          break;
×
70
        }
×
71

×
72
        rpos++; upos++;
73
      }
×
74
      return route[rpos] == requrl.path[upos];
×
75
  }
76

77
  RoutingResult Router::route(Request *req, THandlerFunction& handler) {
×
78
    std::map<std::string, TDelim> params;
×
79
    bool matched = false;
×
80
    bool seen = false;
×
81
    std::string rname;
×
82

83
    // iterate routes
×
84
    for (auto& route: routes) {
×
85
      std::string method;
86
      std::string url;
×
87
      funcptr::tie(method, url, handler, rname) = route;
×
88

×
89
      // see if we can't match the url
×
90
      params.clear();
×
91
      // simple matcher func
×
92
      matched = match(url, req->url, params);
×
93

94
      if (matched && !method.empty() && req->method != method) {
×
95
         // method did not match, record it though so we can return correct result
96
         matched = false;
×
97
         seen = true;
×
98
         continue;
99
      }
×
100
      if (matched) {
×
101
        break;
×
102
      }
×
103
    }
×
104

×
105
    if (!matched) {
×
106
      if (seen) {
×
107
        return RouteNoMethod;
×
108
      }
×
109
      // no route
×
110
      return RouteNotFound;
×
111
    }
×
112

113
    req->parameters.clear();
114

115
    for (const auto& param: params) {
×
116
      int nstart = 0;
×
117
      int nend = 0;
118
      funcptr::tie(nstart, nend) = param.second;
×
119
      std::string value(req->url.path.begin() + nstart, req->url.path.begin() + nend);
×
120
      value = Utility::decodeURL(value);
×
121
      req->parameters[param.first] = std::move(value);
×
122
    }
123

×
124
    req->routeName = std::move(rname);
×
125

×
126
    return RouteFound;
×
127
  };
128

129
  void Router::printRoutes(std::ostream &os) {
130
    for(TRouteList::iterator i = routes.begin(); i != routes.end(); i++) {
×
131
#if __cplusplus >= 201103L
132
      std::streamsize ss = os.width();
×
133
      std::ios::fmtflags ff = os.setf(std::ios::left);
×
134
      os.width(10);
135
      os << std::get<0>(*i);
×
136
      os.width(50);
×
137
      os << std::get<1>(*i);
×
138
      os.width(ss);
×
139
      os.setf(ff);
×
140
      os << "    " << std::get<3>(*i);
×
141
      os << std::endl;
×
142
#else
×
143
      os << i->get<0>() << "    " << i->get<1>() << "    " << i->get<3>() << std::endl;
×
144
#endif
×
145
    } 
×
146
  };
×
147

×
148
  std::pair<std::string,std::string> Router::urlFor(const std::string &name, const strstr_map_t& arguments) {
×
149
    std::ostringstream path;
×
150
    std::string mask,method,result;
×
151
    int k1,k2,k3;
152

×
153
    bool found = false;
×
154
    for(TRouteList::iterator i = routes.begin(); !found && i != routes.end(); i++) {
×
155
#if __cplusplus >= 201103L
×
156
      if (std::get<3>(*i) == name) { mask = std::get<1>(*i); method = std::get<0>(*i); found = true; }
×
157
#else
×
158
      if (i->get<3>() == name) { mask = i->get<1>(); method = i->get<0>(); found = true; }
×
159
#endif
×
160
    }
161

162
    if (!found)
163
      throw Error("Route not found");
164

165
    for(k1=0,k3=0;k1<static_cast<int>(mask.size());k1++) {
166
      if (mask[k1] == '<') {
167
        std::string pname;
168
        strstr_map_t::const_iterator pptr;
169
        k2=k1;
170
        while(k1<static_cast<int>(mask.size()) && mask[k1]!='>') k1++;
171
        path << mask.substr(k3,k2-k3);
172
        if (mask[k2+1] == '*')
173
          pname = std::string(mask.begin() + k2 + 2, mask.begin() + k1);
174
        else 
175
          pname = std::string(mask.begin() + k2 + 1, mask.begin() + k1);
176
        if ((pptr = arguments.find(pname)) != arguments.end()) 
177
          path << Utility::encodeURL(pptr->second);
178
        k3 = k1+1;
179
      }
180
      else if (mask[k1] == '*') {
181
        // ready 
182
        k3++;
183
        continue;
184
      }
185
    }
186
    path << mask.substr(k3);
187
    result = path.str();
188
    return std::make_pair(method, result);
189
  }
190
};
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc