![]() |
RTBKit
0.9
Open-source framework to create real-time ad bidding systems.
|
00001 00011 #pragma once 00012 00013 #include "rest_request_router.h" 00014 #include "jml/arch/demangle.h" 00015 #include <boost/lexical_cast.hpp> 00016 #include "json_codec.h" 00017 00018 00019 namespace Datacratic { 00020 00021 template<typename T> 00022 struct RestParam { 00023 RestParam(const std::string & name, const std::string & description) 00024 : name(name), description(description) 00025 { 00026 //std::cerr << "created RestParam with " << name << " at " 00027 // << this << std::endl; 00028 } 00029 00030 RestParam(const RestParam & other) 00031 : name(other.name), description(other.description) 00032 { 00033 //std::cerr << "copied RestParam with " << name << " to " 00034 // << this << std::endl; 00035 } 00036 00037 std::string name; 00038 std::string description; 00039 00040 private: 00041 void operator = (const RestParam & other); 00042 }; 00043 00044 template<typename T> 00045 struct RestParamDefault { 00046 RestParamDefault(const std::string & name, const std::string & description, 00047 T defaultValue) 00048 : name(name), description(description), defaultValue(defaultValue), 00049 defaultValueStr(boost::lexical_cast<std::string>(defaultValue)) 00050 { 00051 //std::cerr << "created RestParam with " << name << " at " 00052 // << this << std::endl; 00053 } 00054 00055 RestParamDefault(const RestParamDefault & other) 00056 : name(other.name), description(other.description), 00057 defaultValue(other.defaultValue), 00058 defaultValueStr(other.defaultValueStr) 00059 { 00060 //std::cerr << "copied RestParam with " << name << " to " 00061 // << this << std::endl; 00062 } 00063 00064 std::string name; 00065 std::string description; 00066 T defaultValue; 00067 std::string defaultValueStr; 00068 00069 private: 00070 void operator = (const RestParamDefault & other); 00071 }; 00072 00073 template<typename T> 00074 struct JsonParam { 00075 JsonParam(const std::string & name, const std::string & description) 00076 : name(name), description(description) 00077 { 00078 } 00079 00080 JsonParam(const JsonParam & other) 00081 : name(other.name), description(other.description) 00082 { 00083 } 00084 00085 std::string name; 00086 std::string description; 00087 }; 00088 00089 template<typename T> 00090 struct RequestParam { 00091 RequestParam(int index, const std::string & name, const std::string & description) 00092 : index(index), name(name), description(description) 00093 { 00094 } 00095 00096 RequestParam(const RequestParam & other) 00097 : index(other.index), 00098 name(other.name), 00099 description(other.description) 00100 { 00101 } 00102 00103 int index; 00104 std::string name; 00105 std::string description; 00106 }; 00107 00108 template<typename T> 00109 decltype(boost::lexical_cast<T>(std::declval<std::string>())) 00110 restDecode(const std::string & str, T * = 0) 00111 { 00112 return boost::lexical_cast<T>(str); 00113 } 00114 00115 template<typename T> 00116 std::string restEncode(const T & val, 00117 decltype(boost::lexical_cast<std::string>(std::declval<T>())) * = 0) 00118 { 00119 return boost::lexical_cast<std::string>(val); 00120 } 00121 00122 template<typename T, typename Enable = void> 00123 struct RestCodec { 00124 static T decode(const std::string & str) 00125 { 00126 return restDecode(str, (T *)0); 00127 } 00128 00129 static std::string encode(const T & val) 00130 { 00131 return restEncode(val); 00132 } 00133 }; 00134 00135 00139 template<typename T> 00140 std::function<T (const RestServiceEndpoint::ConnectionId & connection, 00141 const RestRequest & request, 00142 const RestRequestParsingContext & context)> 00143 createParameterExtractor(Json::Value & argHelp, const T & p, void * = 0) 00144 { 00145 return [=] (const RestServiceEndpoint::ConnectionId & connection, 00146 const RestRequest & request, 00147 const RestRequestParsingContext & context) 00148 { 00149 return p; 00150 }; 00151 } 00152 00154 struct StringPayload { 00155 StringPayload(const std::string & description) 00156 : description(description) 00157 { 00158 } 00159 00160 std::string description; 00161 }; 00162 00163 inline static std::function<std::string 00164 (const RestServiceEndpoint::ConnectionId & connection, 00165 const RestRequest & request, 00166 const RestRequestParsingContext & context)> 00167 createParameterExtractor(Json::Value & argHelp, 00168 const StringPayload & p, void * = 0) 00169 { 00170 Json::Value & v = argHelp["payload"]; 00171 v["description"] = p.description; 00172 00173 return [=] (const RestServiceEndpoint::ConnectionId & connection, 00174 const RestRequest & request, 00175 const RestRequestParsingContext & context) 00176 { 00177 return request.payload; 00178 }; 00179 } 00180 00181 struct PassConnectionId { 00182 }; 00183 00185 inline static std::function<const RestServiceEndpoint::ConnectionId & 00186 (const RestServiceEndpoint::ConnectionId & connection, 00187 const RestRequest & request, 00188 const RestRequestParsingContext & context)> 00189 createParameterExtractor(Json::Value & argHelp, 00190 const PassConnectionId &, void * = 0) 00191 { 00192 return [] (const RestServiceEndpoint::ConnectionId & connection, 00193 const RestRequest & request, 00194 const RestRequestParsingContext & context) 00195 -> const RestServiceEndpoint::ConnectionId & 00196 { 00197 return connection; 00198 }; 00199 } 00200 00205 template<typename T> 00206 static std::function<decltype(RestCodec<T>::decode(std::declval<std::string>())) 00207 (const RestServiceEndpoint::ConnectionId & connection, 00208 const RestRequest & request, 00209 const RestRequestParsingContext & context)> 00210 createParameterExtractor(Json::Value & argHelp, 00211 const RestParam<T> & p, void * = 0) 00212 { 00213 ExcAssertNotEqual(p.name, ""); 00214 00215 Json::Value & v = argHelp["requestParams"]; 00216 Json::Value & v2 = v[v.size()]; 00217 if (!p.name.empty()) 00218 v2["name"] = p.name; 00219 v2["description"] = p.description; 00220 v2["cppType"] = ML::type_name<T>(); 00221 v2["encoding"] = "URI encoded"; 00222 v2["location"] = "query string"; 00223 00224 return [=] (const RestServiceEndpoint::ConnectionId & connection, 00225 const RestRequest & request, 00226 const RestRequestParsingContext & context) 00227 { 00228 //std::cerr << "getting value of " << p.name << std::endl; 00229 std::string paramValue = request.params.getValue(p.name); 00230 return RestCodec<T>::decode(paramValue); 00231 }; 00232 } 00233 00234 template<typename T> 00235 static std::function<T (const RestServiceEndpoint::ConnectionId & connection, 00236 const RestRequest & request, 00237 const RestRequestParsingContext & context)> 00238 createParameterExtractor(Json::Value & argHelp, 00239 const RestParamDefault<T> & p, void * = 0) 00240 { 00241 ExcAssertNotEqual(p.name, ""); 00242 00243 Json::Value & v = argHelp["requestParams"]; 00244 Json::Value & v2 = v[v.size()]; 00245 if (!p.name.empty()) 00246 v2["name"] = p.name; 00247 v2["description"] = p.description; 00248 v2["cppType"] = ML::type_name<T>(); 00249 v2["encoding"] = "URI encoded"; 00250 v2["location"] = "query string"; 00251 v2["defaultValue"] = p.defaultValueStr; 00252 00253 return [=] (const RestServiceEndpoint::ConnectionId & connection, 00254 const RestRequest & request, 00255 const RestRequestParsingContext & context) 00256 { 00257 //std::cerr << "getting value of " << p.name << std::endl; 00258 std::string paramValue; 00259 T result; 00260 if (request.params.hasValue(p.name)) 00261 result = RestCodec<T>::decode(request.params.getValue(p.name)); 00262 else result = p.defaultValue; 00263 return result; 00264 }; 00265 } 00266 00271 template<typename T> 00272 static std::function<decltype(JsonCodec<T>::decode(std::declval<Json::Value>())) 00273 (const RestServiceEndpoint::ConnectionId & connection, 00274 const RestRequest & request, 00275 const RestRequestParsingContext & context)> 00276 createParameterExtractor(Json::Value & argHelp, 00277 const JsonParam<T> & p, void * = 0) 00278 { 00279 Json::Value & v = argHelp["jsonParams"]; 00280 Json::Value & v2 = v[v.size()]; 00281 if (!p.name.empty()) 00282 v2["name"] = p.name; 00283 v2["description"] = p.description; 00284 v2["cppType"] = ML::type_name<T>(); 00285 v2["encoding"] = "JSON"; 00286 v2["location"] = "Request Body"; 00287 00288 return [=] (const RestServiceEndpoint::ConnectionId & connection, 00289 const RestRequest & request, 00290 const RestRequestParsingContext & context) 00291 { 00292 Json::Value parsed = Json::parse(request.payload); 00293 return JsonCodec<T>::decode(p.name.empty() ? parsed : parsed[p.name]); 00294 }; 00295 } 00296 00301 template<typename T> 00302 static std::function<decltype(RestCodec<T>::decode(std::declval<std::string>())) 00303 (const RestServiceEndpoint::ConnectionId & connection, 00304 const RestRequest & request, 00305 const RestRequestParsingContext & context)> 00306 createParameterExtractor(Json::Value & argHelp, 00307 const RequestParam<T> & p, void * = 0) 00308 { 00309 Json::Value & v = argHelp["resourceParams"]; 00310 Json::Value & v2 = v[v.size()]; 00311 if (!p.name.empty()) 00312 v2["name"] = p.name; 00313 v2["description"] = p.description; 00314 v2["cppType"] = ML::type_name<T>(); 00315 v2["encoding"] = "URI encoded"; 00316 v2["location"] = "URI"; 00317 00318 return [=] (const RestServiceEndpoint::ConnectionId & connection, 00319 const RestRequest & request, 00320 const RestRequestParsingContext & context) 00321 { 00322 int index = p.index; 00323 //using namespace std; 00324 //cerr << "index " << index << " with " 00325 // << context.resources.size() << " resources" << endl; 00326 if (index < 0) 00327 index = context.resources.size() + index; 00328 std::string paramValue = context.resources.at(index); 00329 return RestCodec<T>::decode(paramValue); 00330 }; 00331 } 00332 00346 template<typename Fn, typename Return, typename... Args> 00347 std::function<std::function<Return (Args...)> 00348 (const RestServiceEndpoint::ConnectionId & connection, 00349 const RestRequest & request, 00350 const RestRequestParsingContext & context)> 00351 createParameterExtractor(Json::Value argHelp, 00352 const Fn & fn, std::function<Return (Args...)> * = 0) 00353 { 00354 return [=] (const RestServiceEndpoint::ConnectionId & connection, 00355 const RestRequest & request, 00356 const RestRequestParsingContext & context) 00357 { 00358 // TODO: deal with more/less than one parameter... 00359 return std::bind(fn, std::placeholders::_1, connection, request); 00360 }; 00361 } 00362 00363 /*************************************************************************/ 00364 /* CREATE GENERATOR */ 00365 /*************************************************************************/ 00366 00395 template<typename X, typename... Params> 00396 struct CreateRestParameterGenerator { 00397 }; 00398 00399 template<int Index, typename Arg, typename Param, typename... Params> 00400 struct CreateRestParameterGenerator<ML::PositionedDualType<Index, Arg, Param>, Params...> { 00401 00402 typedef decltype(createParameterExtractor(*(Json::Value *)0, std::declval<typename ML::ExtractArgAtPosition<0, Index, Params...>::type>(), (typename std::decay<Arg>::type *)0)) Generator; 00403 00404 //typedef std::decay<Arg> Result; 00405 typedef decltype(std::declval<Generator>() 00406 (std::declval<RestServiceEndpoint::ConnectionId>(), 00407 std::declval<RestRequest>(), 00408 std::declval<RestRequestParsingContext>())) Result; 00409 00411 static Generator create(Json::Value & argHelp, Params&&... params) 00412 { 00413 auto param = ML::ExtractArgAtPosition<0, Index, Params...> 00414 ::extract(std::forward<Params>(params)...); 00415 return createParameterExtractor(argHelp, 00416 param, 00417 (typename std::decay<Arg>::type *)0); 00418 } 00419 00425 template<typename Generators> 00426 static Result apply(const Generators & gens, 00427 const RestServiceEndpoint::ConnectionId & connection, 00428 const RestRequest & request, 00429 const RestRequestParsingContext & context) 00430 { 00431 return std::get<Index>(gens)(connection, request, context); 00432 } 00433 }; 00434 00435 template<typename T> 00436 struct RestRequestBinder { 00437 }; 00438 00439 template<typename... PositionedDualTypes> 00440 struct RestRequestBinder<ML::TypeList<PositionedDualTypes...> > { 00441 00445 template<typename Return, typename Obj, typename... Args, typename Ptr, 00446 typename... Params> 00447 static 00448 std::pair<RestRequestRouter::OnProcessRequest, Json::Value> 00449 bindSync(Return (Obj::* pmf) (Args...), 00450 Ptr ptr, 00451 Params&&... params) 00452 { 00453 Json::Value argHelp; 00454 00455 // Create a tuple of function objects that we can call with 00456 auto gens = std::make_tuple(CreateRestParameterGenerator<PositionedDualTypes, Params...> 00457 ::create(argHelp, std::forward<Params>(params)...)...); 00458 // Necessary to deal with a compiler bug 00459 auto sharedGens = std::make_shared<decltype(gens)>(std::move(gens)); 00460 00461 RestRequestRouter::OnProcessRequest result 00462 = [=] (const RestServiceEndpoint::ConnectionId & connection, 00463 const RestRequest & request, 00464 const RestRequestParsingContext & context) 00465 { 00466 auto gens = *sharedGens; 00467 try { 00468 Obj & obj = *ptr; 00469 ((obj).*(pmf))(CreateRestParameterGenerator<PositionedDualTypes, Params...> 00470 ::apply(gens, connection, request, context)... 00471 ); 00472 00473 connection.sendResponse(200); 00474 } catch (const std::exception & exc) { 00475 connection.sendErrorResponse(400, exc.what()); 00476 return RestRequestRouter::MR_ERROR; 00477 } catch (...) { 00478 connection.sendErrorResponse(400, "unknown exception"); 00479 return RestRequestRouter::MR_ERROR; 00480 } 00481 00482 return RestRequestRouter::MR_YES; 00483 }; 00484 00485 return make_pair(result, argHelp); 00486 } 00487 00488 00489 template<typename Return, typename Obj, typename... Args, typename Ptr, 00490 typename... Params> 00491 static 00492 std::pair<RestRequestRouter::OnProcessRequest, Json::Value> 00493 bindSync(Return (Obj::* pmf) (Args...) const, 00494 Ptr ptr, 00495 Params&&... params) 00496 { 00497 Json::Value argHelp; 00498 00499 // Create a tuple of function objects that we can call with 00500 auto gens = std::make_tuple(CreateRestParameterGenerator<PositionedDualTypes, Params...> 00501 ::create(argHelp, std::forward<Params>(params)...)...); 00502 // Necessary to deal with a compiler bug 00503 auto sharedGens = std::make_shared<decltype(gens)>(std::move(gens)); 00504 00505 RestRequestRouter::OnProcessRequest result 00506 = [=] (const RestServiceEndpoint::ConnectionId & connection, 00507 const RestRequest & request, 00508 const RestRequestParsingContext & context) 00509 { 00510 auto gens = *sharedGens; 00511 try { 00512 Obj & obj = *ptr; 00513 ((obj).*(pmf))(CreateRestParameterGenerator<PositionedDualTypes, Params...> 00514 ::apply(gens, connection, request, context)... 00515 ); 00516 00517 connection.sendResponse(200); 00518 } catch (const std::exception & exc) { 00519 connection.sendErrorResponse(400, exc.what()); 00520 return RestRequestRouter::MR_ERROR; 00521 } catch (...) { 00522 connection.sendErrorResponse(400, "unknown exception"); 00523 return RestRequestRouter::MR_ERROR; 00524 } 00525 00526 return RestRequestRouter::MR_YES; 00527 }; 00528 00529 return make_pair(result, argHelp); 00530 } 00531 00535 template<class TransformResultFn, 00536 typename Return, typename Obj, typename... Args, typename Ptr, 00537 typename... Params> 00538 static 00539 std::pair<RestRequestRouter::OnProcessRequest, Json::Value> 00540 bindSyncReturn(const TransformResultFn & fn, 00541 Return (Obj::* pmf) (Args...), 00542 Ptr ptr, 00543 Params&&... params) 00544 { 00545 Json::Value argHelp; 00546 00547 // Create a tuple of function objects that we can call with 00548 auto gens = std::make_tuple(CreateRestParameterGenerator<PositionedDualTypes, Params...> 00549 ::create(argHelp, std::forward<Params>(params)...)...); 00550 // Necessary to deal with a compiler bug 00551 auto sharedGens = std::make_shared<decltype(gens)>(std::move(gens)); 00552 00553 RestRequestRouter::OnProcessRequest result 00554 = [=] (const RestServiceEndpoint::ConnectionId & connection, 00555 const RestRequest & request, 00556 const RestRequestParsingContext & context) 00557 { 00558 auto gens = *sharedGens; 00559 try { 00560 Obj & obj = *ptr; 00561 auto res = ((obj).*(pmf))(CreateRestParameterGenerator<PositionedDualTypes, Params...> 00562 ::apply(gens, connection, request, context)... 00563 ); 00564 connection.sendResponse(200, fn(res)); 00565 } catch (const std::exception & exc) { 00566 connection.sendErrorResponse(400, exc.what()); 00567 return RestRequestRouter::MR_ERROR; 00568 } catch (...) { 00569 connection.sendErrorResponse(400, "unknown exception"); 00570 return RestRequestRouter::MR_ERROR; 00571 } 00572 00573 return RestRequestRouter::MR_YES; 00574 }; 00575 00576 return make_pair(result, argHelp); 00577 } 00578 00579 00580 template<class TransformResultFn, 00581 typename Return, typename Obj, typename... Args, typename Ptr, 00582 typename... Params> 00583 static 00584 std::pair<RestRequestRouter::OnProcessRequest, Json::Value> 00585 bindSyncReturn(const TransformResultFn & fn, 00586 Return (Obj::* pmf) (Args...) const, 00587 Ptr ptr, 00588 Params&&... params) 00589 { 00590 Json::Value argHelp; 00591 00592 // Create a tuple of function objects that we can call with 00593 auto gens = std::make_tuple(CreateRestParameterGenerator<PositionedDualTypes, Params...> 00594 ::create(argHelp, std::forward<Params>(params)...)...); 00595 // Necessary to deal with a compiler bug 00596 auto sharedGens = std::make_shared<decltype(gens)>(std::move(gens)); 00597 00598 RestRequestRouter::OnProcessRequest result 00599 = [=] (const RestServiceEndpoint::ConnectionId & connection, 00600 const RestRequest & request, 00601 const RestRequestParsingContext & context) 00602 { 00603 auto gens = *sharedGens; 00604 try { 00605 Obj & obj = *ptr; 00606 auto res = ((obj).*(pmf))(CreateRestParameterGenerator<PositionedDualTypes, Params...> 00607 ::apply(gens, connection, request, context)... 00608 ); 00609 00610 connection.sendResponse(200, fn(res)); 00611 } catch (const std::exception & exc) { 00612 connection.sendErrorResponse(400, exc.what()); 00613 return RestRequestRouter::MR_ERROR; 00614 } catch (...) { 00615 connection.sendErrorResponse(400, "unknown exception"); 00616 return RestRequestRouter::MR_ERROR; 00617 } 00618 00619 return RestRequestRouter::MR_YES; 00620 }; 00621 00622 return make_pair(result, argHelp); 00623 } 00624 00625 00629 template<typename Return, typename Obj, typename... Args, typename Ptr, 00630 typename... Params> 00631 static 00632 std::pair<RestRequestRouter::OnProcessRequest, Json::Value> 00633 bindSyncReturnStatus(std::pair<int, Return> (Obj::* pmf) (Args...), 00634 Ptr ptr, 00635 Params&&... params) 00636 { 00637 Json::Value argHelp; 00638 00639 // Create a tuple of function objects that we can call with 00640 auto gens = std::make_tuple(CreateRestParameterGenerator<PositionedDualTypes, Params...> 00641 ::create(argHelp, std::forward<Params>(params)...)...); 00642 // Necessary to deal with a compiler bug 00643 auto sharedGens = std::make_shared<decltype(gens)>(std::move(gens)); 00644 00645 RestRequestRouter::OnProcessRequest result 00646 = [=] (const RestServiceEndpoint::ConnectionId & connection, 00647 const RestRequest & request, 00648 const RestRequestParsingContext & context) 00649 { 00650 auto gens = *sharedGens; 00651 try { 00652 Obj & obj = *ptr; 00653 auto res = ((obj).*(pmf))(CreateRestParameterGenerator<PositionedDualTypes, Params...> 00654 ::apply(gens, connection, request, context)... 00655 ); 00656 connection.sendResponse(res.first, res.second); 00657 } catch (const std::exception & exc) { 00658 connection.sendErrorResponse(400, exc.what()); 00659 return RestRequestRouter::MR_ERROR; 00660 } catch (...) { 00661 connection.sendErrorResponse(400, "unknown exception"); 00662 return RestRequestRouter::MR_ERROR; 00663 } 00664 00665 return RestRequestRouter::MR_YES; 00666 }; 00667 00668 return make_pair(result, argHelp); 00669 } 00670 00671 00672 template<typename Return, typename Obj, typename... Args, typename Ptr, 00673 typename... Params> 00674 static 00675 std::pair<RestRequestRouter::OnProcessRequest, Json::Value> 00676 bindSyncReturnStatus(Return (Obj::* pmf) (Args...) const, 00677 Ptr ptr, 00678 Params&&... params) 00679 { 00680 Json::Value argHelp; 00681 00682 // Create a tuple of function objects that we can call with 00683 auto gens = std::make_tuple(CreateRestParameterGenerator<PositionedDualTypes, Params...> 00684 ::create(argHelp, std::forward<Params>(params)...)...); 00685 // Necessary to deal with a compiler bug 00686 auto sharedGens = std::make_shared<decltype(gens)>(std::move(gens)); 00687 00688 RestRequestRouter::OnProcessRequest result 00689 = [=] (const RestServiceEndpoint::ConnectionId & connection, 00690 const RestRequest & request, 00691 const RestRequestParsingContext & context) 00692 { 00693 auto gens = *sharedGens; 00694 try { 00695 Obj & obj = *ptr; 00696 auto res = ((obj).*(pmf))(CreateRestParameterGenerator<PositionedDualTypes, Params...> 00697 ::apply(gens, connection, request, context)... 00698 ); 00699 00700 connection.sendResponse(res.first, res.second); 00701 } catch (const std::exception & exc) { 00702 connection.sendErrorResponse(400, exc.what()); 00703 return RestRequestRouter::MR_ERROR; 00704 } catch (...) { 00705 connection.sendErrorResponse(400, "unknown exception"); 00706 return RestRequestRouter::MR_ERROR; 00707 } 00708 00709 return RestRequestRouter::MR_YES; 00710 }; 00711 00712 return make_pair(result, argHelp); 00713 } 00714 00715 00719 template<typename Return, typename Obj, typename... Args, typename Ptr, 00720 typename... Params> 00721 static 00722 std::pair<RestRequestRouter::OnProcessRequest, Json::Value> 00723 bindAsync(Return (Obj::* pmf) (Args...), 00724 Ptr ptr, 00725 Params&&... params) 00726 { 00727 Json::Value argHelp; 00728 00729 // Create a tuple of function objects that we can call with 00730 auto gens = std::make_tuple(CreateRestParameterGenerator<PositionedDualTypes, Params...> 00731 ::create(argHelp, std::forward<Params>(params)...)...); 00732 // Necessary to deal with a compiler bug 00733 auto sharedGens = std::make_shared<decltype(gens)>(std::move(gens)); 00734 00735 RestRequestRouter::OnProcessRequest result 00736 = [=] (const RestServiceEndpoint::ConnectionId & connection, 00737 const RestRequest & request, 00738 const RestRequestParsingContext & context) 00739 { 00740 auto gens = *sharedGens; 00741 try { 00742 Obj & obj = *ptr; 00743 ((obj).*(pmf))(CreateRestParameterGenerator<PositionedDualTypes, Params...> 00744 ::apply(gens, connection, request, context)... 00745 ); 00746 } catch (const std::exception & exc) { 00747 connection.sendErrorResponse(400, exc.what()); 00748 return RestRequestRouter::MR_ERROR; 00749 } catch (...) { 00750 connection.sendErrorResponse(400, "unknown exception"); 00751 return RestRequestRouter::MR_ERROR; 00752 } 00753 00754 return RestRequestRouter::MR_YES; 00755 }; 00756 00757 return make_pair(result, argHelp); 00758 } 00759 00760 }; 00761 00762 template<typename Return, typename Obj, typename... Args, typename Ptr, 00763 typename TransformResult, 00764 typename... Params> 00765 void 00766 addRouteSyncReturn(RestRequestRouter & router, 00767 PathSpec path, RequestFilter filter, 00768 const std::string & description, 00769 const std::string & resultDescription, 00770 const TransformResult & transformResult, 00771 Return (Obj::* pmf) (Args...), 00772 Ptr ptr, 00773 Params&&... params) 00774 { 00775 static_assert(sizeof...(Args) == sizeof...(Params), 00776 "member function and parameter arity must match"); 00777 00778 typedef ML::TypeList<Args...> ArgsList; 00779 typedef ML::TypeList<Params...> ParamsList; 00780 typedef ML::PositionedDualTypeList<0, ArgsList, ParamsList> PositionedTypes; 00781 00782 auto res = RestRequestBinder<typename PositionedTypes::List> 00783 ::bindSyncReturn(transformResult, 00784 pmf, ptr, std::forward<Params>(params)...); 00785 auto & cb = res.first; 00786 auto & help = res.second; 00787 help["result"] = resultDescription; 00788 00789 router.addRoute(path, filter, description, cb, help); 00790 } 00791 00792 template<typename Return, typename Obj, typename... Args, typename Ptr, 00793 typename TransformResult, 00794 typename... Params> 00795 void 00796 addRouteSyncReturn(RestRequestRouter & router, 00797 PathSpec path, RequestFilter filter, 00798 const std::string & description, 00799 const std::string & resultDescription, 00800 const TransformResult & transformResult, 00801 Return (Obj::* pmf) (Args...) const, 00802 Ptr ptr, 00803 Params&&... params) 00804 { 00805 static_assert(sizeof...(Args) == sizeof...(Params), 00806 "member function and parameter arity must match"); 00807 00808 typedef ML::TypeList<Args...> ArgsList; 00809 typedef ML::TypeList<Params...> ParamsList; 00810 typedef ML::PositionedDualTypeList<0, ArgsList, ParamsList> PositionedTypes; 00811 00812 auto res = RestRequestBinder<typename PositionedTypes::List> 00813 ::bindSyncReturn(transformResult, 00814 pmf, ptr, std::forward<Params>(params)...); 00815 auto & cb = res.first; 00816 auto & help = res.second; 00817 help["result"] = resultDescription; 00818 00819 router.addRoute(path, filter, description, cb, help); 00820 } 00821 00822 template<typename Return, typename Obj, typename... Args, typename Ptr, 00823 typename... Params> 00824 void 00825 addRouteReturnStatus(RestRequestRouter & router, 00826 PathSpec path, RequestFilter filter, 00827 const std::string & description, 00828 const std::string & resultDescription, 00829 std::pair<int, Return> (Obj::* pmf) (Args...), 00830 Ptr ptr, 00831 Params&&... params) 00832 { 00833 static_assert(sizeof...(Args) == sizeof...(Params), 00834 "member function and parameter arity must match"); 00835 00836 typedef ML::TypeList<Args...> ArgsList; 00837 typedef ML::TypeList<Params...> ParamsList; 00838 typedef ML::PositionedDualTypeList<0, ArgsList, ParamsList> PositionedTypes; 00839 00840 auto res = RestRequestBinder<typename PositionedTypes::List> 00841 ::bindSyncReturnStatus(pmf, ptr, std::forward<Params>(params)...); 00842 auto & cb = res.first; 00843 auto & help = res.second; 00844 help["result"] = resultDescription; 00845 00846 router.addRoute(path, filter, description, cb, help); 00847 } 00848 00849 template<typename Return, typename Obj, typename... Args, typename Ptr, 00850 typename... Params> 00851 void 00852 addRouteReturnStatus(RestRequestRouter & router, 00853 PathSpec path, RequestFilter filter, 00854 const std::string & description, 00855 const std::string & resultDescription, 00856 std::pair<int, Return> (Obj::* pmf) (Args...) const, 00857 Ptr ptr, 00858 Params&&... params) 00859 { 00860 static_assert(sizeof...(Args) == sizeof...(Params), 00861 "member function and parameter arity must match"); 00862 00863 typedef ML::TypeList<Args...> ArgsList; 00864 typedef ML::TypeList<Params...> ParamsList; 00865 typedef ML::PositionedDualTypeList<0, ArgsList, ParamsList> PositionedTypes; 00866 00867 auto res = RestRequestBinder<typename PositionedTypes::List> 00868 ::bindSyncReturnStatus(pmf, ptr, std::forward<Params>(params)...); 00869 auto & cb = res.first; 00870 auto & help = res.second; 00871 help["result"] = resultDescription; 00872 00873 router.addRoute(path, filter, description, cb, help); 00874 } 00875 00876 // Void return types don't need to convert their result 00877 template<typename Return, typename Obj, typename... Args, typename Ptr, 00878 typename... Params> 00879 void 00880 addRouteSync(RestRequestRouter & router, 00881 PathSpec path, RequestFilter filter, 00882 const std::string & description, 00883 Return (Obj::* pmf) (Args...), 00884 Ptr ptr, 00885 Params&&... params) 00886 { 00887 static_assert(sizeof...(Args) == sizeof...(Params), 00888 "member function and parameter arity must match"); 00889 00890 typedef ML::TypeList<Args...> ArgsList; 00891 typedef ML::TypeList<Params...> ParamsList; 00892 typedef ML::PositionedDualTypeList<0, ArgsList, ParamsList> PositionedTypes; 00893 00894 auto res = RestRequestBinder<typename PositionedTypes::List> 00895 ::bindSync(pmf, ptr, std::forward<Params>(params)...); 00896 auto & cb = res.first; 00897 auto & help = res.second; 00898 00899 router.addRoute(path, filter, description, cb, help); 00900 } 00901 00902 // Void return types don't need to convert their result 00903 template<typename Return, typename Obj, typename... Args, typename Ptr, 00904 typename... Params> 00905 void 00906 addRouteSync(RestRequestRouter & router, 00907 PathSpec path, RequestFilter filter, 00908 const std::string & description, 00909 Return (Obj::* pmf) (Args...) const, 00910 Ptr ptr, 00911 Params&&... params) 00912 { 00913 static_assert(sizeof...(Args) == sizeof...(Params), 00914 "member function and parameter arity must match"); 00915 00916 typedef ML::TypeList<Args...> ArgsList; 00917 typedef ML::TypeList<Params...> ParamsList; 00918 typedef ML::PositionedDualTypeList<0, ArgsList, ParamsList> PositionedTypes; 00919 00920 auto res = RestRequestBinder<typename PositionedTypes::List> 00921 ::bindSync(pmf, ptr, std::forward<Params>(params)...); 00922 auto & cb = res.first; 00923 auto & help = res.second; 00924 00925 router.addRoute(path, filter, description, cb, help); 00926 } 00927 00928 template<typename Return, typename Obj, typename... Args, typename Ptr, 00929 typename... Params> 00930 void 00931 addRouteAsync(RestRequestRouter & router, 00932 PathSpec path, RequestFilter filter, 00933 const std::string & description, 00934 Return (Obj::* pmf) (Args...), 00935 Ptr ptr, 00936 Params&&... params) 00937 { 00938 static_assert(sizeof...(Args) == sizeof...(Params), 00939 "member function and parameter arity must match"); 00940 00941 typedef ML::TypeList<Args...> ArgsList; 00942 typedef ML::TypeList<Params...> ParamsList; 00943 typedef ML::PositionedDualTypeList<0, ArgsList, ParamsList> PositionedTypes; 00944 00945 auto res = RestRequestBinder<typename PositionedTypes::List> 00946 ::bindAsync(pmf, ptr, std::forward<Params>(params)...); 00947 auto & cb = res.first; 00948 auto & help = res.second; 00949 00950 router.addRoute(path, filter, description, cb, help); 00951 } 00952 00953 template<typename Return, typename Obj, typename... Args, typename Ptr, 00954 typename... Params> 00955 void 00956 addRouteAsync(RestRequestRouter & router, 00957 PathSpec path, RequestFilter filter, 00958 const std::string & description, 00959 Return (Obj::* pmf) (Args...) const, 00960 Ptr ptr, 00961 Params&&... params) 00962 { 00963 static_assert(sizeof...(Args) == sizeof...(Params), 00964 "member function and parameter arity must match"); 00965 00966 typedef ML::TypeList<Args...> ArgsList; 00967 typedef ML::TypeList<Params...> ParamsList; 00968 typedef ML::PositionedDualTypeList<0, ArgsList, ParamsList> PositionedTypes; 00969 00970 auto res = RestRequestBinder<typename PositionedTypes::List> 00971 ::bindAsync(pmf, ptr, std::forward<Params>(params)...); 00972 auto & cb = res.first; 00973 auto & help = res.second; 00974 00975 router.addRoute(path, filter, description, cb, help); 00976 } 00977 00978 } // namespace Datacratic