1 #pragma once
2 /* @file
3  * @brief Defines router class and support structures
4  */
5 #ifdef HAVE_CXX11
6 #include <functional>
7 #include <tuple>
8 #define HAVE_CPP_FUNC_PTR
9 #define IGNORE std::ignore
10 namespace funcptr = std;
11 #else
12 #ifdef HAVE_BOOST
13 #include <boost/function.hpp>
14 #include <boost/tuple/tuple.hpp>
15 #define IGNORE boost::tuples::ignore
16 namespace funcptr = boost;
17 #define HAVE_CPP_FUNC_PTR
18 #else
19 #warning "You need to configure with boost or have C++11 capable compiler for router"
20 #endif
21 #endif
22 
23 #ifdef HAVE_CPP_FUNC_PTR
24 #include <vector>
25 #include <utility>
26 
27 namespace YaHTTP {
28   typedef funcptr::function <void(Request* req, Response* resp)> THandlerFunction; //!< Handler function pointer
29   typedef funcptr::tuple<std::string, std::string, THandlerFunction, std::string> TRoute; //!< Route tuple (method, urlmask, handler, name)
30   typedef std::vector<TRoute> TRouteList; //!< List of routes in order of evaluation
31 
32   /*! Implements simple router.
33 
34 This class implements a router for masked urls. The URL mask syntax is as of follows
35 
36 /&lt;masked&gt;/url&lt;number&gt;/&lt;hi&gt;.&lt;format&gt;
37 
38 You can use &lt;*param&gt; to denote that everything will be matched and consumed into the parameter, including slash (/). Use &lt;*&gt; to denote that URL
39 is consumed but not stored. Note that only path is matched, scheme, host and url parameters are ignored.
40    */
41   class Router {
42   private:
Router()43     Router() {};
44     static Router router; //<! Singleton instance of Router
45   public:
46     void map(const std::string& method, const std::string& url, THandlerFunction handler, const std::string& name); //<! Instance method for mapping urls
47     bool route(Request *req, THandlerFunction& handler); //<! Instance method for performing routing
48     void printRoutes(std::ostream &os); //<! Instance method for printing routes
49     std::pair<std::string, std::string> urlFor(const std::string &name, const strstr_map_t& arguments); //<! Instance method for generating paths
50 
51 /*! Map an URL.
52 If method is left empty, it will match any method. Name is also optional, but needed if you want to find it for making URLs
53 */
Map(const std::string & method,const std::string & url,THandlerFunction handler,const std::string & name="")54     static void Map(const std::string& method, const std::string& url, THandlerFunction handler, const std::string& name = "") { router.map(method, url, handler, name); };
Get(const std::string & url,THandlerFunction handler,const std::string & name="")55     static void Get(const std::string& url, THandlerFunction handler, const std::string& name = "") { router.map("GET", url, handler, name); }; //<! Helper for mapping GET
Post(const std::string & url,THandlerFunction handler,const std::string & name="")56     static void Post(const std::string& url, THandlerFunction handler, const std::string& name = "") { router.map("POST", url, handler, name); }; //<! Helper for mapping POST
Put(const std::string & url,THandlerFunction handler,const std::string & name="")57     static void Put(const std::string& url, THandlerFunction handler, const std::string& name = "") { router.map("PUT", url, handler, name); }; //<! Helper for mapping PUT
Patch(const std::string & url,THandlerFunction handler,const std::string & name="")58     static void Patch(const std::string& url, THandlerFunction handler, const std::string& name = "") { router.map("PATCH", url, handler, name); }; //<! Helper for mapping PATCH
Delete(const std::string & url,THandlerFunction handler,const std::string & name="")59     static void Delete(const std::string& url, THandlerFunction handler, const std::string& name = "") { router.map("DELETE", url, handler, name); }; //<! Helper for mapping DELETE
Any(const std::string & url,THandlerFunction handler,const std::string & name="")60     static void Any(const std::string& url, THandlerFunction handler, const std::string& name = "") { router.map("", url, handler, name); }; //<! Helper for mapping any method
61 
Route(Request * req,THandlerFunction & handler)62     static bool Route(Request *req, THandlerFunction& handler) { return router.route(req, handler); }; //<! Performs routing based on req->url.path
PrintRoutes(std::ostream & os)63     static void PrintRoutes(std::ostream &os) { router.printRoutes(os); }; //<! Prints all known routes to given output stream
64 
URLFor(const std::string & name,const strstr_map_t & arguments)65     static std::pair<std::string, std::string> URLFor(const std::string &name, const strstr_map_t& arguments) { return router.urlFor(name,arguments); }; //<! Generates url from named route and arguments. Missing arguments are assumed empty
GetRoutes()66     static const TRouteList& GetRoutes() { return router.routes; } //<! Reference to route list
Clear()67     static void Clear() { router.routes.clear(); } //<! Clear all routes
68 
69     TRouteList routes; //<! Instance variable for routes
70   };
71 };
72 #endif
73