base_define.hpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582
  1. /***************************************************************************
  2. *
  3. * Project _____ __ ____ _ _
  4. * ( _ ) /__\ (_ _)_| |_ _| |_
  5. * )(_)( /(__)\ )( (_ _)(_ _)
  6. * (_____)(__)(__)(__) |_| |_|
  7. *
  8. *
  9. * Copyright 2018-present, Leonid Stryzhevskyi <lganzzzo@gmail.com>
  10. *
  11. * Licensed under the Apache License, Version 2.0 (the "License");
  12. * you may not use this file except in compliance with the License.
  13. * You may obtain a copy of the License at
  14. *
  15. * http://www.apache.org/licenses/LICENSE-2.0
  16. *
  17. * Unless required by applicable law or agreed to in writing, software
  18. * distributed under the License is distributed on an "AS IS" BASIS,
  19. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  20. * See the License for the specific language governing permissions and
  21. * limitations under the License.
  22. *
  23. ***************************************************************************/
  24. #define OATPP_MACRO_API_CONTROLLER_PARAM_MACRO(MACRO, INFO, TYPE, PARAM_LIST) MACRO(TYPE, PARAM_LIST)
  25. #define OATPP_MACRO_API_CONTROLLER_PARAM_INFO(MACRO, INFO, TYPE, PARAM_LIST) INFO(TYPE, PARAM_LIST)
  26. #define OATPP_MACRO_API_CONTROLLER_PARAM_TYPE(MACRO, INFO, TYPE, PARAM_LIST) const TYPE&
  27. #define OATPP_MACRO_API_CONTROLLER_PARAM_NAME(MACRO, INFO, TYPE, PARAM_LIST) OATPP_MACRO_FIRSTARG PARAM_LIST
  28. #define OATPP_MACRO_API_CONTROLLER_PARAM_TYPE_STR(MACRO, INFO, TYPE, PARAM_LIST) #TYPE
  29. #define OATPP_MACRO_API_CONTROLLER_PARAM_NAME_STR(MACRO, INFO, TYPE, PARAM_LIST) OATPP_MACRO_FIRSTARG_STR PARAM_LIST
  30. #define OATPP_MACRO_API_CONTROLLER_PARAM(MACRO, INFO, TYPE, PARAM_LIST) (MACRO, INFO, TYPE, PARAM_LIST)
  31. #define REQUEST(TYPE, ...) \
  32. OATPP_MACRO_API_CONTROLLER_PARAM(OATPP_MACRO_API_CONTROLLER_REQUEST, OATPP_MACRO_API_CONTROLLER_REQUEST_INFO, TYPE, (__VA_ARGS__))
  33. #define HEADER(TYPE, ...) \
  34. OATPP_MACRO_API_CONTROLLER_PARAM(OATPP_MACRO_API_CONTROLLER_HEADER, OATPP_MACRO_API_CONTROLLER_HEADER_INFO, TYPE, (__VA_ARGS__))
  35. #define PATH(TYPE, ...) \
  36. OATPP_MACRO_API_CONTROLLER_PARAM(OATPP_MACRO_API_CONTROLLER_PATH, OATPP_MACRO_API_CONTROLLER_PATH_INFO, TYPE, (__VA_ARGS__))
  37. #define QUERIES(TYPE, ...) \
  38. OATPP_MACRO_API_CONTROLLER_PARAM(OATPP_MACRO_API_CONTROLLER_QUERIES, OATPP_MACRO_API_CONTROLLER_QUERIES_INFO, TYPE, (__VA_ARGS__))
  39. #define QUERY(TYPE, ...) \
  40. OATPP_MACRO_API_CONTROLLER_PARAM(OATPP_MACRO_API_CONTROLLER_QUERY, OATPP_MACRO_API_CONTROLLER_QUERY_INFO, TYPE, (__VA_ARGS__))
  41. #define BODY_STRING(TYPE, ...) \
  42. OATPP_MACRO_API_CONTROLLER_PARAM(OATPP_MACRO_API_CONTROLLER_BODY_STRING, OATPP_MACRO_API_CONTROLLER_BODY_STRING_INFO, TYPE, (__VA_ARGS__))
  43. #define BODY_DTO(TYPE, ...) \
  44. OATPP_MACRO_API_CONTROLLER_PARAM(OATPP_MACRO_API_CONTROLLER_BODY_DTO, OATPP_MACRO_API_CONTROLLER_BODY_DTO_INFO, TYPE, (__VA_ARGS__))
  45. //////////////////////////////////////////////////////////////////////////
  46. #define OATPP_MACRO_API_CONTROLLER_MACRO_SELECTOR(MACRO, TYPE, ...) \
  47. OATPP_MACRO_EXPAND(OATPP_MACRO_MACRO_SELECTOR(MACRO, (__VA_ARGS__)) (TYPE, __VA_ARGS__))
  48. //////////////////////////////////////////////////////////////////////////
  49. // REQUEST MACRO // ------------------------------------------------------
  50. #define OATPP_MACRO_API_CONTROLLER_REQUEST(TYPE, PARAM_LIST) \
  51. const auto& OATPP_MACRO_FIRSTARG PARAM_LIST = __request;
  52. #define OATPP_MACRO_API_CONTROLLER_REQUEST_INFO(TYPE, PARAM_LIST)
  53. // HEADER MACRO // ------------------------------------------------------
  54. #define OATPP_MACRO_API_CONTROLLER_HEADER_1(TYPE, NAME) \
  55. const auto& __param_str_val_##NAME = __request->getHeader(#NAME); \
  56. if(!__param_str_val_##NAME){ \
  57. auto httpError = oatpp::web::protocol::http::HttpError(Status::CODE_400, "Missing HEADER parameter '" #NAME "'"); \
  58. auto eptr = std::make_exception_ptr(httpError); \
  59. return ApiController::handleError(eptr); \
  60. } \
  61. bool __param_validation_check_##NAME; \
  62. const auto& NAME = ApiController::TypeInterpretation<TYPE>::fromString(#TYPE, __param_str_val_##NAME, __param_validation_check_##NAME); \
  63. if(!__param_validation_check_##NAME){ \
  64. auto httpError = oatpp::web::protocol::http::HttpError(Status::CODE_400, "Invalid HEADER parameter '" #NAME "'. Expected type is '" #TYPE "'"); \
  65. auto eptr = std::make_exception_ptr(httpError); \
  66. return ApiController::handleError(eptr); \
  67. }
  68. #define OATPP_MACRO_API_CONTROLLER_HEADER_2(TYPE, NAME, QUALIFIER) \
  69. const auto& __param_str_val_##NAME = __request->getHeader(QUALIFIER); \
  70. if(!__param_str_val_##NAME){ \
  71. auto httpError = oatpp::web::protocol::http::HttpError(Status::CODE_400, oatpp::String("Missing HEADER parameter '") + QUALIFIER + "'"); \
  72. auto eptr = std::make_exception_ptr(httpError); \
  73. return ApiController::handleError(eptr); \
  74. } \
  75. bool __param_validation_check_##NAME; \
  76. const auto& NAME = ApiController::TypeInterpretation<TYPE>::fromString(#TYPE, __param_str_val_##NAME, __param_validation_check_##NAME); \
  77. if(!__param_validation_check_##NAME){ \
  78. auto httpError = oatpp::web::protocol::http::HttpError(Status::CODE_400, \
  79. oatpp::String("Invalid HEADER parameter '") + \
  80. QUALIFIER + \
  81. "'. Expected type is '" #TYPE "'"); \
  82. auto eptr = std::make_exception_ptr(httpError); \
  83. return ApiController::handleError(eptr); \
  84. }
  85. #define OATPP_MACRO_API_CONTROLLER_HEADER(TYPE, PARAM_LIST) \
  86. OATPP_MACRO_API_CONTROLLER_MACRO_SELECTOR(OATPP_MACRO_API_CONTROLLER_HEADER_, TYPE, OATPP_MACRO_UNFOLD_VA_ARGS PARAM_LIST)
  87. // __INFO
  88. #define OATPP_MACRO_API_CONTROLLER_HEADER_INFO_1(TYPE, NAME) \
  89. info->headers.add(#NAME, TYPE::Class::getType());
  90. #define OATPP_MACRO_API_CONTROLLER_HEADER_INFO_2(TYPE, NAME, QUALIFIER) \
  91. info->headers.add(QUALIFIER, TYPE::Class::getType());
  92. #define OATPP_MACRO_API_CONTROLLER_HEADER_INFO(TYPE, PARAM_LIST) \
  93. OATPP_MACRO_API_CONTROLLER_MACRO_SELECTOR(OATPP_MACRO_API_CONTROLLER_HEADER_INFO_, TYPE, OATPP_MACRO_UNFOLD_VA_ARGS PARAM_LIST)
  94. // PATH MACRO // ------------------------------------------------------
  95. #define OATPP_MACRO_API_CONTROLLER_PATH_1(TYPE, NAME) \
  96. const auto& __param_str_val_##NAME = __request->getPathVariable(#NAME); \
  97. if(!__param_str_val_##NAME){ \
  98. auto httpError = oatpp::web::protocol::http::HttpError(Status::CODE_400, "Missing PATH parameter '" #NAME "'"); \
  99. auto eptr = std::make_exception_ptr(httpError); \
  100. return ApiController::handleError(eptr); \
  101. } \
  102. bool __param_validation_check_##NAME; \
  103. const auto& NAME = ApiController::TypeInterpretation<TYPE>::fromString(#TYPE, __param_str_val_##NAME, __param_validation_check_##NAME); \
  104. if(!__param_validation_check_##NAME){ \
  105. auto httpError = oatpp::web::protocol::http::HttpError(Status::CODE_400, "Invalid PATH parameter '" #NAME "'. Expected type is '" #TYPE "'"); \
  106. auto eptr = std::make_exception_ptr(httpError); \
  107. return ApiController::handleError(eptr); \
  108. }
  109. #define OATPP_MACRO_API_CONTROLLER_PATH_2(TYPE, NAME, QUALIFIER) \
  110. const auto& __param_str_val_##NAME = __request->getPathVariable(QUALIFIER); \
  111. if(!__param_str_val_##NAME){ \
  112. auto httpError = oatpp::web::protocol::http::HttpError(Status::CODE_400, \
  113. oatpp::String("Missing PATH parameter '") + QUALIFIER + "'"); \
  114. auto eptr = std::make_exception_ptr(httpError); \
  115. return ApiController::handleError(eptr); \
  116. } \
  117. bool __param_validation_check_##NAME; \
  118. const auto NAME = ApiController::TypeInterpretation<TYPE>::fromString(#TYPE, __param_str_val_##NAME, __param_validation_check_##NAME); \
  119. if(!__param_validation_check_##NAME){ \
  120. auto httpError = oatpp::web::protocol::http::HttpError(Status::CODE_400, \
  121. oatpp::String("Invalid PATH parameter '") + \
  122. QUALIFIER + \
  123. "'. Expected type is '" #TYPE "'"); \
  124. auto eptr = std::make_exception_ptr(httpError); \
  125. return ApiController::handleError(eptr); \
  126. }
  127. #define OATPP_MACRO_API_CONTROLLER_PATH(TYPE, PARAM_LIST) \
  128. OATPP_MACRO_API_CONTROLLER_MACRO_SELECTOR(OATPP_MACRO_API_CONTROLLER_PATH_, TYPE, OATPP_MACRO_UNFOLD_VA_ARGS PARAM_LIST)
  129. // __INFO
  130. #define OATPP_MACRO_API_CONTROLLER_PATH_INFO_1(TYPE, NAME) \
  131. info->pathParams.add(#NAME, TYPE::Class::getType());
  132. #define OATPP_MACRO_API_CONTROLLER_PATH_INFO_2(TYPE, NAME, QUALIFIER) \
  133. info->pathParams.add(QUALIFIER, TYPE::Class::getType());
  134. #define OATPP_MACRO_API_CONTROLLER_PATH_INFO(TYPE, PARAM_LIST) \
  135. OATPP_MACRO_API_CONTROLLER_MACRO_SELECTOR(OATPP_MACRO_API_CONTROLLER_PATH_INFO_, TYPE, OATPP_MACRO_UNFOLD_VA_ARGS PARAM_LIST)
  136. // QUERIES MACRO // ------------------------------------------------------
  137. #define OATPP_MACRO_API_CONTROLLER_QUERIES(TYPE, PARAM_LIST) \
  138. const auto& OATPP_MACRO_FIRSTARG PARAM_LIST = __request->getQueryParameters();
  139. #define OATPP_MACRO_API_CONTROLLER_QUERIES_INFO(TYPE, PARAM_LIST)
  140. // QUERY MACRO // ------------------------------------------------------
  141. #define OATPP_MACRO_API_CONTROLLER_QUERY_1(TYPE, NAME) \
  142. const auto& __param_str_val_##NAME = __request->getQueryParameter(#NAME); \
  143. if(!__param_str_val_##NAME){ \
  144. auto httpError = oatpp::web::protocol::http::HttpError(Status::CODE_400, "Missing QUERY parameter '" #NAME "'"); \
  145. auto eptr = std::make_exception_ptr(httpError); \
  146. return ApiController::handleError(eptr); \
  147. } \
  148. bool __param_validation_check_##NAME; \
  149. const auto& NAME = ApiController::TypeInterpretation<TYPE>::fromString(#TYPE, __param_str_val_##NAME, __param_validation_check_##NAME); \
  150. if(!__param_validation_check_##NAME){ \
  151. auto httpError = oatpp::web::protocol::http::HttpError(Status::CODE_400, "Invalid QUERY parameter '" #NAME "'. Expected type is '" #TYPE "'"); \
  152. auto eptr = std::make_exception_ptr(httpError); \
  153. return ApiController::handleError(eptr); \
  154. }
  155. #define OATPP_MACRO_API_CONTROLLER_QUERY_2(TYPE, NAME, QUALIFIER) \
  156. const auto& __param_str_val_##NAME = __request->getQueryParameter(QUALIFIER); \
  157. if(!__param_str_val_##NAME) \
  158. auto httpError = oatpp::web::protocol::http::HttpError(Status::CODE_400, \
  159. oatpp::String("Missing QUERY parameter '") + QUALIFIER + "'"); \
  160. auto eptr = std::make_exception_ptr(httpError); \
  161. return ApiController::handleError(eptr); \
  162. } \
  163. bool __param_validation_check_##NAME; \
  164. const auto& NAME = ApiController::TypeInterpretation<TYPE>::fromString(#TYPE, __param_str_val_##NAME, __param_validation_check_##NAME); \
  165. if(!__param_validation_check_##NAME){ \
  166. auto httpError = oatpp::web::protocol::http::HttpError(Status::CODE_400, \
  167. oatpp::String("Invalid QUERY parameter '") + \
  168. QUALIFIER + \
  169. "'. Expected type is '" #TYPE "'"); \
  170. auto eptr = std::make_exception_ptr(httpError); \
  171. return ApiController::handleError(eptr); \
  172. }
  173. #define OATPP_MACRO_API_CONTROLLER_QUERY_3(TYPE, NAME, QUALIFIER, DEFAULT) \
  174. TYPE NAME = DEFAULT; \
  175. const auto& __param_str_val_##NAME = __request->getQueryParameter(QUALIFIER); \
  176. if(__param_str_val_##NAME) { \
  177. bool __param_validation_check_##NAME; \
  178. NAME = ApiController::TypeInterpretation<TYPE>::fromString(#TYPE, __param_str_val_##NAME, __param_validation_check_##NAME); \
  179. if(!__param_validation_check_##NAME){ \
  180. auto httpError = oatpp::web::protocol::http::HttpError(Status::CODE_400, \
  181. oatpp::String("Invalid QUERY parameter '") + \
  182. QUALIFIER + \
  183. "'. Expected type is '" #TYPE "'"); \
  184. auto eptr = std::make_exception_ptr(httpError); \
  185. return ApiController::handleError(eptr); \
  186. } \
  187. }
  188. #define OATPP_MACRO_API_CONTROLLER_QUERY(TYPE, PARAM_LIST) \
  189. OATPP_MACRO_API_CONTROLLER_MACRO_SELECTOR(OATPP_MACRO_API_CONTROLLER_QUERY_, TYPE, OATPP_MACRO_UNFOLD_VA_ARGS PARAM_LIST)
  190. // __INFO
  191. #define OATPP_MACRO_API_CONTROLLER_QUERY_INFO_1(TYPE, NAME) \
  192. info->queryParams.add(#NAME, TYPE::Class::getType());
  193. #define OATPP_MACRO_API_CONTROLLER_QUERY_INFO_2(TYPE, NAME, QUALIFIER) \
  194. info->queryParams.add(QUALIFIER, TYPE::Class::getType());
  195. #define OATPP_MACRO_API_CONTROLLER_QUERY_INFO_3(TYPE, NAME, QUALIFIER, DEFAULT) \
  196. info->queryParams.add(QUALIFIER, TYPE::Class::getType());
  197. #define OATPP_MACRO_API_CONTROLLER_QUERY_INFO(TYPE, PARAM_LIST) \
  198. OATPP_MACRO_API_CONTROLLER_MACRO_SELECTOR(OATPP_MACRO_API_CONTROLLER_QUERY_INFO_, TYPE, OATPP_MACRO_UNFOLD_VA_ARGS PARAM_LIST)
  199. // BODY_STRING MACRO // ------------------------------------------------------
  200. #define OATPP_MACRO_API_CONTROLLER_BODY_STRING(TYPE, PARAM_LIST) \
  201. const auto& OATPP_MACRO_FIRSTARG PARAM_LIST = __request->readBodyToString();
  202. // __INFO
  203. #define OATPP_MACRO_API_CONTROLLER_BODY_STRING_INFO(TYPE, PARAM_LIST) \
  204. info->body.name = OATPP_MACRO_FIRSTARG_STR PARAM_LIST; \
  205. info->body.required = true; \
  206. info->body.type = oatpp::data::mapping::type::__class::String::getType(); \
  207. if(getDefaultObjectMapper()) { \
  208. info->bodyContentType = getDefaultObjectMapper()->getInfo().http_content_type; \
  209. }
  210. // BODY_DTO MACRO // ------------------------------------------------------
  211. #define OATPP_MACRO_API_CONTROLLER_BODY_DTO(TYPE, PARAM_LIST) \
  212. if(!getDefaultObjectMapper()) { \
  213. auto httpError = oatpp::web::protocol::http::HttpError(Status::CODE_500, "ObjectMapper was NOT set. Can't deserialize the request body."); \
  214. auto eptr = std::make_exception_ptr(httpError); \
  215. return ApiController::handleError(eptr); \
  216. } \
  217. const auto& OATPP_MACRO_FIRSTARG PARAM_LIST = \
  218. __request->readBodyToDto<TYPE>(getDefaultObjectMapper().get()); \
  219. if(!OATPP_MACRO_FIRSTARG PARAM_LIST) { \
  220. auto httpError = oatpp::web::protocol::http::HttpError(Status::CODE_400, "Missing valid body parameter '" OATPP_MACRO_FIRSTARG_STR PARAM_LIST "'"); \
  221. auto eptr = std::make_exception_ptr(httpError); \
  222. return ApiController::handleError(eptr); \
  223. }
  224. // __INFO
  225. #define OATPP_MACRO_API_CONTROLLER_BODY_DTO_INFO(TYPE, PARAM_LIST) \
  226. info->body.name = OATPP_MACRO_FIRSTARG_STR PARAM_LIST; \
  227. info->body.required = true; \
  228. info->body.type = TYPE::Class::getType(); \
  229. if(getDefaultObjectMapper()) { \
  230. info->bodyContentType = getDefaultObjectMapper()->getInfo().http_content_type; \
  231. }
  232. // FOR EACH // ------------------------------------------------------
  233. #define OATPP_MACRO_API_CONTROLLER_FOR_EACH_PARAM_DECL_FIRST(INDEX, COUNT, X) \
  234. OATPP_MACRO_API_CONTROLLER_PARAM_TYPE X OATPP_MACRO_API_CONTROLLER_PARAM_NAME X
  235. #define OATPP_MACRO_API_CONTROLLER_FOR_EACH_PARAM_DECL_REST(INDEX, COUNT, X) \
  236. , OATPP_MACRO_API_CONTROLLER_PARAM_TYPE X OATPP_MACRO_API_CONTROLLER_PARAM_NAME X
  237. #define OATPP_MACRO_API_CONTROLLER_FOR_EACH_PARAM_PUT(INDEX, COUNT, X) \
  238. OATPP_MACRO_API_CONTROLLER_PARAM_MACRO X
  239. #define OATPP_MACRO_API_CONTROLLER_FOR_EACH_PARAM_CALL_FIRST(INDEX, COUNT, X) \
  240. OATPP_MACRO_API_CONTROLLER_PARAM_NAME X
  241. #define OATPP_MACRO_API_CONTROLLER_FOR_EACH_PARAM_CALL_REST(INDEX, COUNT, X) \
  242. , OATPP_MACRO_API_CONTROLLER_PARAM_NAME X
  243. #define OATPP_MACRO_API_CONTROLLER_FOR_EACH_PARAM_INFO(INDEX, COUNT, X) \
  244. OATPP_MACRO_API_CONTROLLER_PARAM_INFO X
  245. // ENDPOINT_INFO MACRO // ------------------------------------------------------
  246. #define ENDPOINT_INFO(NAME) \
  247. \
  248. std::shared_ptr<oatpp::web::server::api::Endpoint::Info> Z__ENDPOINT_CREATE_ADDITIONAL_INFO_##NAME() { \
  249. auto info = Z__EDNPOINT_INFO_GET_INSTANCE_##NAME(); \
  250. Z__ENDPOINT_ADD_INFO_##NAME(info); \
  251. return info; \
  252. } \
  253. \
  254. const std::shared_ptr<oatpp::web::server::api::Endpoint::Info> Z__ENDPOINT_ADDITIONAL_INFO_##NAME = Z__ENDPOINT_CREATE_ADDITIONAL_INFO_##NAME(); \
  255. \
  256. void Z__ENDPOINT_ADD_INFO_##NAME(const std::shared_ptr<oatpp::web::server::api::Endpoint::Info>& info)
  257. // ENDPOINT MACRO // ------------------------------------------------------
  258. #define OATPP_MACRO_API_CONTROLLER_ENDPOINT_DECL_DEFAULTS(NAME, METHOD, PATH) \
  259. \
  260. template<class T> \
  261. static typename std::shared_ptr<Handler<T>> Z__ENDPOINT_HANDLER_GET_INSTANCE_##NAME(T* controller) { \
  262. auto handler = std::static_pointer_cast<Handler<T>>(controller->getEndpointHandler(#NAME)); \
  263. if(!handler) { \
  264. handler = Handler<T>::createShared(controller, &T::Z__PROXY_METHOD_##NAME, nullptr); \
  265. controller->setEndpointHandler(#NAME, handler); \
  266. } \
  267. return handler; \
  268. } \
  269. \
  270. std::shared_ptr<oatpp::web::server::api::Endpoint::Info> Z__EDNPOINT_INFO_GET_INSTANCE_##NAME() { \
  271. std::shared_ptr<oatpp::web::server::api::Endpoint::Info> info = getEndpointInfo(#NAME); \
  272. if(!info){ \
  273. info = oatpp::web::server::api::Endpoint::Info::createShared(); \
  274. setEndpointInfo(#NAME, info); \
  275. } \
  276. return info; \
  277. }
  278. #define OATPP_MACRO_API_CONTROLLER_ENDPOINT_DECL_0(NAME, METHOD, PATH) \
  279. \
  280. EndpointInfoBuilder Z__CREATE_ENDPOINT_INFO_##NAME = [this](){ \
  281. auto info = Z__EDNPOINT_INFO_GET_INSTANCE_##NAME(); \
  282. info->name = #NAME; \
  283. info->path = ((m_routerPrefix != nullptr) ? m_routerPrefix + PATH : PATH); \
  284. info->method = METHOD; \
  285. if (info->path == "") { \
  286. info->path = "/"; \
  287. } \
  288. return info; \
  289. }; \
  290. \
  291. const std::shared_ptr<oatpp::web::server::api::Endpoint> Z__ENDPOINT_##NAME = createEndpoint(m_endpoints, \
  292. Z__ENDPOINT_HANDLER_GET_INSTANCE_##NAME(this), \
  293. Z__CREATE_ENDPOINT_INFO_##NAME);
  294. #define OATPP_MACRO_API_CONTROLLER_ENDPOINT_0(NAME, METHOD, PATH) \
  295. OATPP_MACRO_API_CONTROLLER_ENDPOINT_DECL_DEFAULTS(NAME, METHOD, PATH) \
  296. OATPP_MACRO_API_CONTROLLER_ENDPOINT_DECL_0(NAME, METHOD, PATH) \
  297. \
  298. std::shared_ptr<oatpp::web::protocol::http::outgoing::Response> \
  299. Z__PROXY_METHOD_##NAME(const std::shared_ptr<oatpp::web::protocol::http::incoming::Request>& __request) \
  300. { \
  301. (void)__request; \
  302. return NAME(); \
  303. } \
  304. \
  305. std::shared_ptr<oatpp::web::protocol::http::outgoing::Response> NAME()
  306. ////////////////////
  307. #define OATPP_MACRO_API_CONTROLLER_ENDPOINT_DECL_1(NAME, METHOD, PATH, ...) \
  308. \
  309. EndpointInfoBuilder Z__CREATE_ENDPOINT_INFO_##NAME = [this](){ \
  310. auto info = Z__EDNPOINT_INFO_GET_INSTANCE_##NAME(); \
  311. info->name = #NAME; \
  312. info->path = ((m_routerPrefix != nullptr) ? m_routerPrefix + PATH : PATH); \
  313. info->method = METHOD; \
  314. OATPP_MACRO_FOREACH(OATPP_MACRO_API_CONTROLLER_FOR_EACH_PARAM_INFO, __VA_ARGS__) \
  315. return info; \
  316. }; \
  317. \
  318. const std::shared_ptr<oatpp::web::server::api::Endpoint> Z__ENDPOINT_##NAME = createEndpoint(m_endpoints, \
  319. Z__ENDPOINT_HANDLER_GET_INSTANCE_##NAME(this), \
  320. Z__CREATE_ENDPOINT_INFO_##NAME);
  321. #define OATPP_MACRO_API_CONTROLLER_ENDPOINT_1(NAME, METHOD, PATH, ...) \
  322. OATPP_MACRO_API_CONTROLLER_ENDPOINT_DECL_DEFAULTS(NAME, METHOD, PATH) \
  323. OATPP_MACRO_API_CONTROLLER_ENDPOINT_DECL_1(NAME, METHOD, PATH, __VA_ARGS__) \
  324. \
  325. std::shared_ptr<oatpp::web::protocol::http::outgoing::Response> \
  326. Z__PROXY_METHOD_##NAME(const std::shared_ptr<oatpp::web::protocol::http::incoming::Request>& __request) \
  327. { \
  328. OATPP_MACRO_FOREACH(OATPP_MACRO_API_CONTROLLER_FOR_EACH_PARAM_PUT, __VA_ARGS__) \
  329. return NAME( \
  330. OATPP_MACRO_FOREACH_FIRST_AND_REST( \
  331. OATPP_MACRO_API_CONTROLLER_FOR_EACH_PARAM_CALL_FIRST, \
  332. OATPP_MACRO_API_CONTROLLER_FOR_EACH_PARAM_CALL_REST, \
  333. __VA_ARGS__ \
  334. ) \
  335. ); \
  336. } \
  337. \
  338. std::shared_ptr<oatpp::web::protocol::http::outgoing::Response> NAME(\
  339. OATPP_MACRO_FOREACH_FIRST_AND_REST( \
  340. OATPP_MACRO_API_CONTROLLER_FOR_EACH_PARAM_DECL_FIRST, \
  341. OATPP_MACRO_API_CONTROLLER_FOR_EACH_PARAM_DECL_REST, \
  342. __VA_ARGS__ \
  343. ) \
  344. )
  345. // Chooser
  346. #define OATPP_MACRO_API_CONTROLLER_ENDPOINT_MACRO_0(METHOD, PATH, NAME) \
  347. OATPP_MACRO_EXPAND(OATPP_MACRO_API_CONTROLLER_ENDPOINT_0(NAME, METHOD, PATH))
  348. #define OATPP_MACRO_API_CONTROLLER_ENDPOINT_MACRO_1(METHOD, PATH, NAME, ...) \
  349. OATPP_MACRO_EXPAND(OATPP_MACRO_API_CONTROLLER_ENDPOINT_1(NAME, METHOD, PATH, __VA_ARGS__))
  350. /**
  351. * Codegen macro to be used in `oatpp::web::server::api::ApiController` to generate Endpoint.
  352. * @param METHOD - Http method ("GET", "POST", "PUT", etc.).
  353. * @param PATH - Path to endpoint (without host).
  354. * @param NAME - Name of the generated method.
  355. * @return - std::shared_ptr to &id:oatpp::web::protocol::http::outgoing::Response;.
  356. */
  357. #define ENDPOINT(METHOD, PATH, ...) \
  358. OATPP_MACRO_EXPAND(OATPP_MACRO_MACRO_BINARY_SELECTOR(OATPP_MACRO_API_CONTROLLER_ENDPOINT_MACRO_, (__VA_ARGS__)) (METHOD, PATH, __VA_ARGS__))
  359. /**
  360. * Endpoint interceptor
  361. */
  362. #define ENDPOINT_INTERCEPTOR(ENDPOINT_NAME, NAME) \
  363. \
  364. Handler<oatpp::web::server::api::ApiController>::Method \
  365. Z__INTERCEPTOR_METHOD_##ENDPOINT_NAME ##_ ##NAME = Z__INTERCEPTOR_METHOD_SET_##ENDPOINT_NAME ##_ ##NAME(this); \
  366. \
  367. template<class T> \
  368. Handler<oatpp::web::server::api::ApiController>::Method Z__INTERCEPTOR_METHOD_SET_##ENDPOINT_NAME ##_ ##NAME (T* controller) { \
  369. return static_cast<Handler<oatpp::web::server::api::ApiController>::Method>( \
  370. Z__ENDPOINT_HANDLER_GET_INSTANCE_##ENDPOINT_NAME(controller)->setMethod(&T::Z__PROXY_INTERCEPTOR_METHOD_##ENDPOINT_NAME ##_ ##NAME) \
  371. ); \
  372. } \
  373. \
  374. std::shared_ptr<oatpp::web::protocol::http::outgoing::Response> \
  375. Z__PROXY_INTERCEPTOR_METHOD_##ENDPOINT_NAME ##_ ##NAME(const std::shared_ptr<oatpp::web::protocol::http::incoming::Request>& request) { \
  376. return Z__USER_PROXY_INTERCEPTOR_METHOD_##ENDPOINT_NAME ##_ ##NAME(this, request); \
  377. } \
  378. \
  379. template<class T> \
  380. std::shared_ptr<oatpp::web::protocol::http::outgoing::Response> \
  381. Z__USER_PROXY_INTERCEPTOR_METHOD_##ENDPOINT_NAME ##_ ##NAME( \
  382. T*, \
  383. const std::shared_ptr<oatpp::web::protocol::http::incoming::Request>& request \
  384. ) { \
  385. auto intercepted = static_cast<typename Handler<T>::Method>(Z__INTERCEPTOR_METHOD_##ENDPOINT_NAME ##_ ##NAME); \
  386. return Z__USER_INTERCEPTOR_METHOD_##ENDPOINT_NAME ##_ ##NAME <T> (intercepted, request); \
  387. } \
  388. \
  389. template<class T> \
  390. std::shared_ptr<oatpp::web::protocol::http::outgoing::Response> \
  391. Z__USER_INTERCEPTOR_METHOD_##ENDPOINT_NAME ##_ ##NAME( \
  392. typename Handler<T>::Method intercepted, \
  393. const std::shared_ptr<oatpp::web::protocol::http::incoming::Request>& request \
  394. )
  395. // ENDPOINT ASYNC MACRO // ------------------------------------------------------
  396. /*
  397. * 1 - Method to obtain endpoint call function ptr
  398. * 2 - Endpoint info singleton
  399. */
  400. #define OATPP_MACRO_API_CONTROLLER_ENDPOINT_ASYNC_DECL_DEFAULTS(NAME, METHOD, PATH) \
  401. \
  402. template<class T> \
  403. static typename std::shared_ptr<Handler<T>> Z__ENDPOINT_HANDLER_GET_INSTANCE_##NAME(T* controller) { \
  404. auto handler = std::static_pointer_cast<Handler<T>>(controller->getEndpointHandler(#NAME)); \
  405. if(!handler) { \
  406. handler = Handler<T>::createShared(controller, nullptr, &T::Z__PROXY_METHOD_##NAME); \
  407. controller->setEndpointHandler(#NAME, handler); \
  408. } \
  409. return handler; \
  410. } \
  411. \
  412. std::shared_ptr<oatpp::web::server::api::Endpoint::Info> Z__EDNPOINT_INFO_GET_INSTANCE_##NAME() { \
  413. std::shared_ptr<oatpp::web::server::api::Endpoint::Info> info = getEndpointInfo(#NAME); \
  414. if(!info){ \
  415. info = oatpp::web::server::api::Endpoint::Info::createShared(); \
  416. setEndpointInfo(#NAME, info); \
  417. } \
  418. return info; \
  419. }
  420. /*
  421. * 1 - Endpoint info instance
  422. * 2 - Endpoint instance
  423. */
  424. #define OATPP_MACRO_API_CONTROLLER_ENDPOINT_ASYNC_DECL(NAME, METHOD, PATH) \
  425. \
  426. EndpointInfoBuilder Z__CREATE_ENDPOINT_INFO_##NAME = [this](){ \
  427. auto info = Z__EDNPOINT_INFO_GET_INSTANCE_##NAME(); \
  428. info->name = #NAME; \
  429. info->path = PATH; \
  430. info->method = METHOD; \
  431. return info; \
  432. }; \
  433. \
  434. const std::shared_ptr<oatpp::web::server::api::Endpoint> Z__ENDPOINT_##NAME = createEndpoint(m_endpoints, \
  435. Z__ENDPOINT_HANDLER_GET_INSTANCE_##NAME(this), \
  436. Z__CREATE_ENDPOINT_INFO_##NAME);
  437. /**
  438. * Codegen macro to be used in `oatpp::web::server::api::ApiController` to generate Asynchronous Endpoint.
  439. * @param METHOD - Http method ("GET", "POST", "PUT", etc.).
  440. * @param PATH - Path to endpoint (without host).
  441. * @param NAME - Name of the generated method.
  442. * @return - &id:oatpp::async::Action;.
  443. */
  444. #define ENDPOINT_ASYNC(METHOD, PATH, NAME) \
  445. OATPP_MACRO_API_CONTROLLER_ENDPOINT_ASYNC_DECL_DEFAULTS(NAME, METHOD, PATH) \
  446. OATPP_MACRO_API_CONTROLLER_ENDPOINT_ASYNC_DECL(NAME, METHOD, PATH) \
  447. \
  448. oatpp::async::CoroutineStarterForResult<const std::shared_ptr<oatpp::web::protocol::http::outgoing::Response>&> \
  449. Z__PROXY_METHOD_##NAME(const std::shared_ptr<oatpp::web::protocol::http::incoming::Request>& __request) \
  450. { \
  451. return NAME::startForResult(this, __request); \
  452. } \
  453. \
  454. class NAME : public HandlerCoroutine<NAME, __ControllerType>
  455. /**
  456. * Auxiliary codegen macro for `ENDPOINT_ASYNC` to generate correct constructor for Asynchronous Endpoint Coroutine.
  457. * @NAME - Name of the endpoint. Exact the same name as was passed to `ENDPOINT_ASYNC` macro.
  458. */
  459. #define ENDPOINT_ASYNC_INIT(NAME) \
  460. public: \
  461. \
  462. NAME(__ControllerType* pController, \
  463. const std::shared_ptr<IncomingRequest>& pRequest) \
  464. : HandlerCoroutine(pController, pRequest) \
  465. {}
  466. /**
  467. * Endpoint interceptor
  468. */
  469. #define ENDPOINT_INTERCEPTOR_ASYNC(ENDPOINT_NAME, NAME) \
  470. \
  471. Handler<oatpp::web::server::api::ApiController>::MethodAsync \
  472. Z__INTERCEPTOR_METHOD_##ENDPOINT_NAME ##_ ##NAME = Z__INTERCEPTOR_METHOD_SET_##ENDPOINT_NAME ##_ ##NAME(this); \
  473. \
  474. template<class T> \
  475. Handler<oatpp::web::server::api::ApiController>::MethodAsync Z__INTERCEPTOR_METHOD_SET_##ENDPOINT_NAME ##_ ##NAME (T* controller) { \
  476. return static_cast<Handler<oatpp::web::server::api::ApiController>::MethodAsync>( \
  477. Z__ENDPOINT_HANDLER_GET_INSTANCE_##ENDPOINT_NAME(controller)->setMethodAsync(&T::Z__PROXY_INTERCEPTOR_METHOD_##ENDPOINT_NAME ##_ ##NAME) \
  478. ); \
  479. } \
  480. \
  481. oatpp::async::CoroutineStarterForResult<const std::shared_ptr<oatpp::web::protocol::http::outgoing::Response>&> \
  482. Z__PROXY_INTERCEPTOR_METHOD_##ENDPOINT_NAME ##_ ##NAME(const std::shared_ptr<oatpp::web::protocol::http::incoming::Request>& request) { \
  483. return Z__USER_PROXY_INTERCEPTOR_METHOD_##ENDPOINT_NAME ##_ ##NAME(this, request); \
  484. } \
  485. \
  486. template<class T> \
  487. oatpp::async::CoroutineStarterForResult<const std::shared_ptr<oatpp::web::protocol::http::outgoing::Response>&> \
  488. Z__USER_PROXY_INTERCEPTOR_METHOD_##ENDPOINT_NAME ##_ ##NAME( \
  489. T*, \
  490. const std::shared_ptr<oatpp::web::protocol::http::incoming::Request>& request \
  491. ) { \
  492. auto intercepted = static_cast<typename Handler<T>::MethodAsync>(Z__INTERCEPTOR_METHOD_##ENDPOINT_NAME ##_ ##NAME); \
  493. return Z__USER_INTERCEPTOR_METHOD_##ENDPOINT_NAME ##_ ##NAME <T> (intercepted, request); \
  494. } \
  495. \
  496. template<class T> \
  497. oatpp::async::CoroutineStarterForResult<const std::shared_ptr<oatpp::web::protocol::http::outgoing::Response>&> \
  498. Z__USER_INTERCEPTOR_METHOD_##ENDPOINT_NAME ##_ ##NAME( \
  499. typename Handler<T>::MethodAsync intercepted, \
  500. const std::shared_ptr<oatpp::web::protocol::http::incoming::Request>& request \
  501. )