RTBKit
0.9
Open-source framework to create real-time ad bidding systems.
|
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