RTBKit  0.9
Open-source framework to create real-time ad bidding systems.
soa/service/rest_request_router.h
00001 
00007 #pragma once
00008 
00009 #include "soa/service/named_endpoint.h"
00010 #include "soa/service/message_loop.h"
00011 #include "soa/service/rest_service_endpoint.h"
00012 #include "jml/utils/vector_utils.h"
00013 #include "jml/utils/positioned_types.h"
00014 //#include <regex>
00015 #include <boost/regex.hpp>
00016 
00017 namespace Datacratic {
00018 
00019 
00020 /*****************************************************************************/
00021 /* PATH SPEC                                                                 */
00022 /*****************************************************************************/
00023 
00026 struct PathSpec {
00027     enum Type {
00028         NONE,
00029         STRING,
00030         REGEX
00031     } type;
00032 
00033     PathSpec()
00034         : type(NONE)
00035     {
00036     }
00037         
00038     PathSpec(const std::string & fullPath)
00039         : type(STRING), path(fullPath)
00040     {
00041     }
00042 
00043     PathSpec(const char * fullPath)
00044         : type(STRING), path(fullPath)
00045     {
00046     }
00047 
00048     PathSpec(const std::string & str, const boost::regex & rex)
00049         : type(REGEX),
00050           path(str),
00051           rex(rex)
00052     {
00053     }
00054 
00055     void getHelp(Json::Value & result)
00056     {
00057         switch (type) {
00058         case STRING:
00059             result["path"] = path;
00060             break;
00061         case REGEX: {
00062             Json::Value & v = result["path"];
00063             v["regex"] = path;
00064             v["desc"] = desc;
00065             break;
00066         }
00067         default:
00068             throw ML::Exception("unknown path parameter");
00069         }
00070     }
00071     
00072     std::string getPathDesc() const
00073     {
00074         if (!desc.empty())
00075             return desc;
00076         return path;
00077     }
00078 
00079     std::string path;
00080     boost::regex rex;
00081     std::string desc;
00082 
00083     bool operator == (const PathSpec & other) const
00084     {
00085         return path == other.path;
00086     }
00087 
00088     bool operator != (const PathSpec & other) const
00089     {
00090         return ! operator == (other);
00091     }
00092 
00093     bool operator < (const PathSpec & other) const
00094     {
00095         return path < other.path;
00096     }
00097 };
00098 
00099 struct Rx : public PathSpec {
00100     Rx(const std::string & regexString, const std::string & desc)
00101         : PathSpec(regexString, boost::regex(regexString))
00102     {
00103         this->desc = desc;
00104     }
00105 };
00106 
00107 std::ostream & operator << (std::ostream & stream, const PathSpec & path);
00108 
00109 
00110 /*****************************************************************************/
00111 /* REQUEST FILTER                                                            */
00112 /*****************************************************************************/
00113 
00116 struct RequestFilter {
00117     RequestFilter()
00118     {
00119     }
00120 
00121     RequestFilter(const std::string & verb)
00122     {
00123         verbs.insert(verb);
00124     }
00125 
00126     RequestFilter(const char * verb)
00127     {
00128         verbs.insert(verb);
00129     }
00130 
00131     RequestFilter(std::set<std::string> verbs)
00132         : verbs(verbs)
00133     {
00134     }
00135 
00136     RequestFilter(const std::initializer_list<std::string> & verbs)
00137         : verbs(verbs)
00138     {
00139     }
00140 
00141     void getHelp(Json::Value & result)
00142     {
00143         if (!verbs.empty()) {
00144             int i = 0;
00145             for (auto it = verbs.begin(), end = verbs.end(); it != end;  ++it, ++i) {
00146                 result["verbs"][i] = *it;
00147             }
00148         }
00149     }
00150 
00151     std::set<std::string> verbs;
00152 };
00153 
00154 std::ostream & operator << (std::ostream & stream, const RequestFilter & filter);
00155 
00156 /*****************************************************************************/
00157 /* REQUEST REQUEST PARSING CONTEXT                                           */
00158 /*****************************************************************************/
00159 
00164 struct RestRequestParsingContext {
00165     RestRequestParsingContext(const RestRequest & request)
00166         : remaining(request.resource)
00167     {
00168     }
00169 
00170     std::vector<std::string> resources;
00171     std::string remaining;
00172 };
00173 
00174 std::ostream & operator << (std::ostream & stream,
00175                             const RestRequestParsingContext & context);
00176 
00177 
00178 /*****************************************************************************/
00179 /* REST REQUEST ROUTER                                                       */
00180 /*****************************************************************************/
00181 
00182 struct RestRequestRouter {
00183 
00184     enum MatchResult {
00185         MR_NO,     
00186         MR_YES,    
00187         MR_ERROR   
00188     };    
00189 
00190     typedef std::function<MatchResult (const RestServiceEndpoint::ConnectionId & connection,
00191                                        const RestRequest & request,
00192                                        const RestRequestParsingContext & context)>
00193          OnProcessRequest;
00194 
00195     RestRequestRouter();
00196 
00197     RestRequestRouter(const OnProcessRequest & processRequest,
00198                       const std::string & description,
00199                       bool terminal,
00200                       const Json::Value & argHelp = Json::Value());
00201 
00202     virtual ~RestRequestRouter();
00203     
00207     RestServiceEndpoint::OnHandleRequest requestHandler() const;
00208 
00209     virtual void handleRequest(const RestServiceEndpoint::ConnectionId & connection,
00210                                const RestRequest & request) const;
00211 
00212     virtual MatchResult
00213     processRequest(const RestServiceEndpoint::ConnectionId & connection,
00214                    const RestRequest & request,
00215                    RestRequestParsingContext & context) const;
00216 
00217     struct Route {
00218         PathSpec path;
00219         RequestFilter filter;
00220         std::shared_ptr<RestRequestRouter> router;
00221 
00222         MatchResult process(const RestRequest & request,
00223                             const RestRequestParsingContext & context,
00224                             const RestServiceEndpoint::ConnectionId & connection) const;
00225     };
00226 
00230     void addRoute(PathSpec path, RequestFilter filter,
00231                   const std::shared_ptr<RestRequestRouter> & handler);
00232 
00236     void addRoute(PathSpec path, RequestFilter filter,
00237                   const std::string & description,
00238                   const OnProcessRequest & cb,
00239                   const Json::Value & argHelp);
00240 
00241     void addHelpRoute(PathSpec path, RequestFilter filter);
00242 
00243     virtual void getHelp(Json::Value & result,
00244                          const std::string & currentPath,
00245                          const std::set<std::string> & verbs);
00246 
00247     RestRequestRouter &
00248     addSubRouter(PathSpec path, const std::string & description);
00249     
00250     OnProcessRequest rootHandler;
00251     std::vector<Route> subRoutes;
00252     std::string description;
00253     bool terminal;
00254     Json::Value argHelp;
00255 };
00256 
00257 
00258 } // namespace Datacratic
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator