60
60
#include < boost/algorithm/string.hpp>
61
61
#include < fmt/core.h>
62
62
63
- using boost::fusion::make_cons;
64
- using boost::fusion::invoke;
65
-
66
- namespace al = boost::algorithm;
67
63
68
64
/* *
69
65
* maps router DSL expressions to constructors for handlers. this means it's
@@ -77,21 +73,10 @@ struct router {
77
73
virtual bool invoke_if (const std::vector<std::string> &, request &, handler_ptr_t &) = 0;
78
74
};
79
75
80
- using rule_ptr = std::unique_ptr<rule_base>;
81
-
82
76
// concrete rule match / constructor class
83
- template <typename rule_t , typename func_t >
77
+ template <typename rule_t , typename Handler>
84
78
struct rule : public rule_base {
85
- // the DSL rule expression to match
86
- rule_t r;
87
-
88
- // the function to call (used later as constructor factory)
89
- func_t func;
90
-
91
- rule (rule_t r_, func_t f_) :
92
- r (std::move(r_)),
93
- func (f_)
94
- {}
79
+ explicit rule (rule_t && r_) : r(std::move(r_)) {}
95
80
96
81
// try to match the expression. if it succeeds, call the provided function
97
82
// with the provided params and the matched DSL arguments.
@@ -101,15 +86,24 @@ struct router {
101
86
try {
102
87
auto begin = parts.begin ();
103
88
auto sequence = r.match (begin, parts.end ());
104
- if (begin!=parts.end ())
89
+
90
+ if (begin != parts.end ())
105
91
throw match::error ();
92
+
106
93
ptr.reset (
107
- invoke (func, make_cons (std::ref (params), sequence)));
108
- return true ;
94
+ boost::fusion::invoke (func, boost::fusion::make_cons (std::ref (params), sequence)));
109
95
} catch (const match::error &e) {
110
96
return false ;
111
97
}
98
+ return true ;
112
99
}
100
+
101
+ private:
102
+ // the DSL rule expression to match
103
+ rule_t r;
104
+
105
+ // the function to call (used later as constructor factory)
106
+ boost::factory<Handler *> func{};
113
107
};
114
108
115
109
/* add a match all methods rule (a DSL expression) which constructs the Handler
@@ -119,47 +113,36 @@ struct router {
119
113
*/
120
114
121
115
// add rule to match HTTP GET method only
122
- template <typename Handler, typename Rule> router& GET (Rule r) {
123
- // functor to create Handler instances
124
- boost::factory<Handler *> ctor;
116
+ template <typename Handler, typename Rule> router& GET (Rule&& r) {
125
117
126
118
static_assert (std::is_base_of<handler, Handler>::value, " GET rule requires handler subclass" );
127
119
static_assert (!std::is_base_of<payload_enabled_handler, Handler>::value, " GET rule cannot use payload enabled handler subclass" );
128
120
129
- rules_get.push_back (
130
- rule_ptr (new rule<Rule, boost::factory<Handler *> >(std::move (r), ctor)));
121
+ rules_get.push_back (std::make_unique<rule<Rule, Handler> >(std::move (r)));
131
122
return *this ;
132
123
}
133
124
134
125
// add rule to match HTTP POST method only
135
- template <typename Handler, typename Rule> router& POST (Rule r) {
136
- // functor to create Handler instances
137
- boost::factory<Handler *> ctor;
126
+ template <typename Handler, typename Rule> router& POST (Rule&& r) {
138
127
139
128
static_assert (std::is_base_of<payload_enabled_handler, Handler>::value, " POST rule requires payload enabled handler subclass" );
140
129
141
- rules_post.push_back (
142
- rule_ptr (new rule<Rule, boost::factory<Handler *> >(std::move (r), ctor)));
130
+ rules_post.push_back (std::make_unique<rule<Rule, Handler> >(std::move (r)));
143
131
return *this ;
144
132
}
145
133
146
-
147
134
// add rule to match HTTP PUT method only
148
- template <typename Handler, typename Rule> router& PUT (Rule r) {
149
- // functor to create Handler instances
150
- boost::factory<Handler *> ctor;
135
+ template <typename Handler, typename Rule> router& PUT (Rule&& r) {
151
136
152
137
static_assert (std::is_base_of<payload_enabled_handler, Handler>::value, " PUT rule requires payload enabled handler subclass" );
153
138
154
- rules_put.push_back (
155
- rule_ptr (new rule<Rule, boost::factory<Handler *> >(std::move (r), ctor)));
139
+ rules_put.push_back (std::make_unique<rule<Rule, Handler> >(std::move (r)));
156
140
return *this ;
157
141
}
158
142
159
143
/* match the list of path components given in p. if a match is found,
160
- * construct an
161
- * object of the handler type with the provided params and the matched
162
- * params.
144
+ * construct an object of the handler type with the provided params
145
+ * and the matched params.
163
146
*/
164
147
165
148
handler_ptr_t match (const std::vector<std::string> &p, request ¶ms) {
@@ -221,6 +204,8 @@ struct router {
221
204
}
222
205
223
206
private:
207
+ using rule_ptr = std::unique_ptr<rule_base>;
208
+
224
209
std::vector<rule_ptr> rules_get;
225
210
std::vector<rule_ptr> rules_post;
226
211
std::vector<rule_ptr> rules_put;
@@ -291,43 +276,44 @@ namespace {
291
276
std::pair<std::string, mime::type> resource_mime_type (const std::string &path) {
292
277
293
278
#if HAVE_YAJL
294
- {
295
- std::size_t json_found = path.rfind (" .json" );
296
279
297
- if (json_found != std::string::npos && json_found == path.length () - 5 ) {
298
- return std::make_pair (path.substr (0 , json_found), mime::type::application_json);
299
- }
300
- }
280
+ std::size_t json_found = path.rfind (" .json" );
281
+
282
+ if (json_found != std::string::npos && json_found == path.length () - 5 ) {
283
+ return {path.substr (0 , json_found), mime::type::application_json};
284
+ }
285
+
301
286
#endif
302
287
303
- {
304
- std::size_t xml_found = path.rfind (" .xml" );
288
+ std::size_t xml_found = path.rfind (" .xml" );
305
289
306
- if (xml_found != std::string::npos && xml_found == path.length () - 4 ) {
307
- return make_pair (path.substr (0 , xml_found), mime::type::application_xml);
308
- }
309
- }
290
+ if (xml_found != std::string::npos && xml_found == path.length () - 4 ) {
291
+ return {path.substr (0 , xml_found), mime::type::application_xml};
292
+ }
310
293
311
- return make_pair (path, mime::type::unspecified_type);
294
+ return make_pair (path, mime::type::unspecified_type);
312
295
}
313
296
314
297
handler_ptr_t route_resource (request &req, const std::string &path,
315
298
const std::unique_ptr<router> &r) {
299
+
300
+ namespace al = boost::algorithm;
301
+
316
302
// strip off the format-spec, if there is one
317
- std::pair<std::string, mime::type> resource = resource_mime_type (path);
303
+ auto [ resource, mime_type] = resource_mime_type (path);
318
304
319
305
// split the URL into bits to be matched.
320
306
std::vector<std::string> path_components;
321
- al::split (path_components, resource. first , al::is_any_of (" /" ));
307
+ al::split (path_components, resource, al::is_any_of (" /" ));
322
308
323
- handler_ptr_t hptr (r->match (path_components, req));
309
+ auto hptr (r->match (path_components, req));
324
310
325
311
// if the pointer points at something, then the path was found. otherwise,
326
312
// it must have exhausted all the possible routes.
327
313
if (hptr) {
328
314
// ugly hack - need this info later on to choose the output formatter,
329
315
// but don't want to parse the URI again...
330
- hptr->set_resource_type (resource. second );
316
+ hptr->set_resource_type (mime_type );
331
317
}
332
318
333
319
return hptr;
0 commit comments