diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index adf8b22b..5b8638dd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -5,6 +5,10 @@ add_library(oatpp oatpp/algorithm/CRC.cpp oatpp/algorithm/CRC.hpp + oatpp/codegen/api_controller/base_define.hpp + oatpp/codegen/api_controller/base_undef.hpp + oatpp/codegen/api_controller/auth_define.hpp + oatpp/codegen/api_controller/auth_undef.hpp oatpp/codegen/codegen_define_ApiClient_.hpp oatpp/codegen/codegen_define_ApiController_.hpp oatpp/codegen/codegen_define_DTO_.hpp diff --git a/src/oatpp/codegen/api_controller/auth_define.hpp b/src/oatpp/codegen/api_controller/auth_define.hpp new file mode 100644 index 00000000..51fdbf3a --- /dev/null +++ b/src/oatpp/codegen/api_controller/auth_define.hpp @@ -0,0 +1,67 @@ +/*************************************************************************** + * + * Project _____ __ ____ _ _ + * ( _ ) /__\ (_ _)_| |_ _| |_ + * )(_)( /(__)\ )( (_ _)(_ _) + * (_____)(__)(__)(__) |_| |_| + * + * + * Copyright 2018-present, Leonid Stryzhevskyi <lganzzzo@gmail.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************/ + +#define AUTHORIZATION(TYPE, ...) \ +OATPP_MACRO_API_CONTROLLER_PARAM(OATPP_MACRO_API_CONTROLLER_AUTHORIZATION, OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_INFO, TYPE, (__VA_ARGS__)) + +// AUTHORIZATION MACRO // ------------------------------------------------------ + +#define OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_1(TYPE, NAME) \ +auto __param_str_val_##NAME = __request->getHeader(oatpp::web::protocol::http::Header::AUTHORIZATION); \ +std::shared_ptr<oatpp::web::server::handler::AuthorizationObject> __param_aosp_val_##NAME = ApiController::handleDefaultAuthorization(__param_str_val_##NAME); \ +TYPE NAME = std::static_pointer_cast<TYPE::element_type>(__param_aosp_val_##NAME); + +#define OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_2(TYPE, NAME, AUTH_HANDLER) \ +auto __param_str_val_##NAME = __request->getHeader(oatpp::web::protocol::http::Header::AUTHORIZATION); \ +std::shared_ptr<oatpp::web::server::handler::AuthorizationHandler> __auth_handler_##NAME = AUTH_HANDLER; \ +std::shared_ptr<oatpp::web::server::handler::AuthorizationObject> __param_aosp_val_##NAME = __auth_handler_##NAME->handleAuthorization(__param_str_val_##NAME); \ +TYPE NAME = std::static_pointer_cast<TYPE::element_type>(__param_aosp_val_##NAME); + +#define OATPP_MACRO_API_CONTROLLER_AUTHORIZATION(TYPE, PARAM_LIST) \ +OATPP_MACRO_API_CONTROLLER_MACRO_SELECTOR(OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_, TYPE, OATPP_MACRO_UNFOLD_VA_ARGS PARAM_LIST) + +// __INFO + +#define OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_INFO_1(TYPE, NAME) \ +auto __param_obj_##NAME = ApiController::getDefaultAuthorizationHandler(); \ +if(__param_obj_##NAME) { \ + info->headers.add(oatpp::web::protocol::http::Header::AUTHORIZATION, oatpp::String::Class::getType()); \ + info->headers[oatpp::web::protocol::http::Header::AUTHORIZATION].description = __param_obj_##NAME ->getScheme(); \ + info->authorization = __param_obj_##NAME ->getScheme(); \ +} else { \ + throw oatpp::web::protocol::http::HttpError(Status::CODE_500, "No authorization handler set up in controller before controller was added to router or swagger-doc."); \ +} + +#define OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_INFO_2(TYPE, NAME, AUTH_HANDLER) \ +std::shared_ptr<oatpp::web::server::handler::AuthorizationHandler> __auth_handler_##NAME = AUTH_HANDLER; \ +if(__auth_handler_##NAME) { \ + info->headers.add(oatpp::web::protocol::http::Header::AUTHORIZATION, oatpp::String::Class::getType()); \ + info->headers[oatpp::web::protocol::http::Header::AUTHORIZATION].description = __auth_handler_##NAME->getScheme(); \ + info->authorization = __auth_handler_##NAME->getScheme(); \ +} else { \ + throw oatpp::web::protocol::http::HttpError(Status::CODE_500, "Invalid authorization handler given (or not set up) in AUTHORIZATION(TYPE, NAME, AUTH_HANDLER) before controller was added to router or swagger-doc."); \ +} + +#define OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_INFO(TYPE, PARAM_LIST) \ +OATPP_MACRO_API_CONTROLLER_MACRO_SELECTOR(OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_INFO_, TYPE, OATPP_MACRO_UNFOLD_VA_ARGS PARAM_LIST) diff --git a/src/oatpp/codegen/api_controller/auth_undef.hpp b/src/oatpp/codegen/api_controller/auth_undef.hpp new file mode 100644 index 00000000..f2984caa --- /dev/null +++ b/src/oatpp/codegen/api_controller/auth_undef.hpp @@ -0,0 +1,35 @@ +/*************************************************************************** + * + * Project _____ __ ____ _ _ + * ( _ ) /__\ (_ _)_| |_ _| |_ + * )(_)( /(__)\ )( (_ _)(_ _) + * (_____)(__)(__)(__) |_| |_| + * + * + * Copyright 2018-present, Leonid Stryzhevskyi <lganzzzo@gmail.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************/ + +#undef AUTHORIZATION + +// AUTHORIZATION MACRO // ------------------------------------------------------ +#undef OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_1 +#undef OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_2 +#undef OATPP_MACRO_API_CONTROLLER_AUTHORIZATION + +// __INFO +#undef OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_INFO_1 +#undef OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_INFO_2 +#undef OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_INFO diff --git a/src/oatpp/codegen/api_controller/base_define.hpp b/src/oatpp/codegen/api_controller/base_define.hpp new file mode 100644 index 00000000..d6edd490 --- /dev/null +++ b/src/oatpp/codegen/api_controller/base_define.hpp @@ -0,0 +1,522 @@ +/*************************************************************************** + * + * Project _____ __ ____ _ _ + * ( _ ) /__\ (_ _)_| |_ _| |_ + * )(_)( /(__)\ )( (_ _)(_ _) + * (_____)(__)(__)(__) |_| |_| + * + * + * Copyright 2018-present, Leonid Stryzhevskyi <lganzzzo@gmail.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************/ + +#define OATPP_MACRO_API_CONTROLLER_PARAM_MACRO(MACRO, INFO, TYPE, PARAM_LIST) MACRO(TYPE, PARAM_LIST) +#define OATPP_MACRO_API_CONTROLLER_PARAM_INFO(MACRO, INFO, TYPE, PARAM_LIST) INFO(TYPE, PARAM_LIST) +#define OATPP_MACRO_API_CONTROLLER_PARAM_TYPE(MACRO, INFO, TYPE, PARAM_LIST) TYPE +#define OATPP_MACRO_API_CONTROLLER_PARAM_NAME(MACRO, INFO, TYPE, PARAM_LIST) OATPP_MACRO_FIRSTARG PARAM_LIST +#define OATPP_MACRO_API_CONTROLLER_PARAM_TYPE_STR(MACRO, INFO, TYPE, PARAM_LIST) #TYPE +#define OATPP_MACRO_API_CONTROLLER_PARAM_NAME_STR(MACRO, INFO, TYPE, PARAM_LIST) OATPP_MACRO_FIRSTARG_STR PARAM_LIST +#define OATPP_MACRO_API_CONTROLLER_PARAM(MACRO, INFO, TYPE, PARAM_LIST) (MACRO, INFO, TYPE, PARAM_LIST) + +#define REQUEST(TYPE, ...) \ +OATPP_MACRO_API_CONTROLLER_PARAM(OATPP_MACRO_API_CONTROLLER_REQUEST, OATPP_MACRO_API_CONTROLLER_REQUEST_INFO, TYPE, (__VA_ARGS__)) + +#define HEADER(TYPE, ...) \ +OATPP_MACRO_API_CONTROLLER_PARAM(OATPP_MACRO_API_CONTROLLER_HEADER, OATPP_MACRO_API_CONTROLLER_HEADER_INFO, TYPE, (__VA_ARGS__)) + +#define PATH(TYPE, ...) \ +OATPP_MACRO_API_CONTROLLER_PARAM(OATPP_MACRO_API_CONTROLLER_PATH, OATPP_MACRO_API_CONTROLLER_PATH_INFO, TYPE, (__VA_ARGS__)) + +#define QUERIES(TYPE, ...) \ +OATPP_MACRO_API_CONTROLLER_PARAM(OATPP_MACRO_API_CONTROLLER_QUERIES, OATPP_MACRO_API_CONTROLLER_QUERIES_INFO, TYPE, (__VA_ARGS__)) + +#define QUERY(TYPE, ...) \ +OATPP_MACRO_API_CONTROLLER_PARAM(OATPP_MACRO_API_CONTROLLER_QUERY, OATPP_MACRO_API_CONTROLLER_QUERY_INFO, TYPE, (__VA_ARGS__)) + +#define BODY_STRING(TYPE, ...) \ +OATPP_MACRO_API_CONTROLLER_PARAM(OATPP_MACRO_API_CONTROLLER_BODY_STRING, OATPP_MACRO_API_CONTROLLER_BODY_STRING_INFO, TYPE, (__VA_ARGS__)) + +#define BODY_DTO(TYPE, ...) \ +OATPP_MACRO_API_CONTROLLER_PARAM(OATPP_MACRO_API_CONTROLLER_BODY_DTO, OATPP_MACRO_API_CONTROLLER_BODY_DTO_INFO, TYPE, (__VA_ARGS__)) + +////////////////////////////////////////////////////////////////////////// + +#define OATPP_MACRO_API_CONTROLLER_MACRO_SELECTOR(MACRO, TYPE, ...) \ +OATPP_MACRO_EXPAND(OATPP_MACRO_MACRO_SELECTOR(MACRO, (__VA_ARGS__)) (TYPE, __VA_ARGS__)) + +////////////////////////////////////////////////////////////////////////// + +// REQUEST MACRO // ------------------------------------------------------ + +#define OATPP_MACRO_API_CONTROLLER_REQUEST(TYPE, PARAM_LIST) \ +TYPE OATPP_MACRO_FIRSTARG PARAM_LIST = __request; + +#define OATPP_MACRO_API_CONTROLLER_REQUEST_INFO(TYPE, PARAM_LIST) + + +// HEADER MACRO // ------------------------------------------------------ + +#define OATPP_MACRO_API_CONTROLLER_HEADER_1(TYPE, NAME) \ +auto __param_str_val_##NAME = __request->getHeader(#NAME); \ +if(!__param_str_val_##NAME){ \ + return ApiController::handleError(Status::CODE_400, "Missing HEADER parameter '" #NAME "'"); \ +} \ +bool __param_validation_check_##NAME; \ +TYPE NAME = TYPE::Class::parseFromString(__param_str_val_##NAME, __param_validation_check_##NAME); \ +if(!__param_validation_check_##NAME){ \ + return ApiController::handleError(Status::CODE_400, "Invalid HEADER parameter '" #NAME "'. Expected type is '" #TYPE "'"); \ +} + +#define OATPP_MACRO_API_CONTROLLER_HEADER_2(TYPE, NAME, QUALIFIER) \ +auto __param_str_val_##NAME = __request->getHeader(QUALIFIER); \ +if(!__param_str_val_##NAME){ \ + return ApiController::handleError(Status::CODE_400, \ + oatpp::String("Missing HEADER parameter '") + QUALIFIER + "'"); \ +} \ +bool __param_validation_check_##NAME; \ +TYPE NAME = TYPE::Class::parseFromString(__param_str_val_##NAME, __param_validation_check_##NAME); \ +if(!__param_validation_check_##NAME){ \ + return ApiController::handleError(Status::CODE_400, \ + oatpp::String("Invalid HEADER parameter '") + \ + QUALIFIER + \ + "'. Expected type is '" #TYPE "'"); \ +} + +#define OATPP_MACRO_API_CONTROLLER_HEADER(TYPE, PARAM_LIST) \ +OATPP_MACRO_API_CONTROLLER_MACRO_SELECTOR(OATPP_MACRO_API_CONTROLLER_HEADER_, TYPE, OATPP_MACRO_UNFOLD_VA_ARGS PARAM_LIST) + +// __INFO + +#define OATPP_MACRO_API_CONTROLLER_HEADER_INFO_1(TYPE, NAME) \ +info->headers.add(#NAME, TYPE::Class::getType()); + +#define OATPP_MACRO_API_CONTROLLER_HEADER_INFO_2(TYPE, NAME, QUALIFIER) \ +info->headers.add(QUALIFIER, TYPE::Class::getType()); + +#define OATPP_MACRO_API_CONTROLLER_HEADER_INFO(TYPE, PARAM_LIST) \ +OATPP_MACRO_API_CONTROLLER_MACRO_SELECTOR(OATPP_MACRO_API_CONTROLLER_HEADER_INFO_, TYPE, OATPP_MACRO_UNFOLD_VA_ARGS PARAM_LIST) + + +// PATH MACRO // ------------------------------------------------------ + +#define OATPP_MACRO_API_CONTROLLER_PATH_1(TYPE, NAME) \ +auto __param_str_val_##NAME = __request->getPathVariable(#NAME); \ +if(!__param_str_val_##NAME){ \ + return ApiController::handleError(Status::CODE_400, "Missing PATH parameter '" #NAME "'"); \ +} \ +bool __param_validation_check_##NAME; \ +TYPE NAME = TYPE::Class::parseFromString(__param_str_val_##NAME, __param_validation_check_##NAME); \ +if(!__param_validation_check_##NAME){ \ + return ApiController::handleError(Status::CODE_400, "Invalid PATH parameter '" #NAME "'. Expected type is '" #TYPE "'"); \ +} + +#define OATPP_MACRO_API_CONTROLLER_PATH_2(TYPE, NAME, QUALIFIER) \ +auto __param_str_val_##NAME = __request->getPathVariable(QUALIFIER); \ +if(!__param_str_val_##NAME){ \ + return ApiController::handleError(Status::CODE_400, \ + oatpp::String("Missing PATH parameter '") + QUALIFIER + "'"); \ +} \ +bool __param_validation_check_##NAME; \ +TYPE NAME = TYPE::Class::parseFromString(__param_str_val_##NAME, __param_validation_check_##NAME); \ +if(!__param_validation_check_##NAME){ \ + return ApiController::handleError(Status::CODE_400, \ + oatpp::String("Invalid PATH parameter '") + \ + QUALIFIER + \ + "'. Expected type is '" #TYPE "'"); \ +} + +#define OATPP_MACRO_API_CONTROLLER_PATH(TYPE, PARAM_LIST) \ +OATPP_MACRO_API_CONTROLLER_MACRO_SELECTOR(OATPP_MACRO_API_CONTROLLER_PATH_, TYPE, OATPP_MACRO_UNFOLD_VA_ARGS PARAM_LIST) + +// __INFO + +#define OATPP_MACRO_API_CONTROLLER_PATH_INFO_1(TYPE, NAME) \ +info->pathParams.add(#NAME, TYPE::Class::getType()); + +#define OATPP_MACRO_API_CONTROLLER_PATH_INFO_2(TYPE, NAME, QUALIFIER) \ +info->pathParams.add(QUALIFIER, TYPE::Class::getType()); + +#define OATPP_MACRO_API_CONTROLLER_PATH_INFO(TYPE, PARAM_LIST) \ +OATPP_MACRO_API_CONTROLLER_MACRO_SELECTOR(OATPP_MACRO_API_CONTROLLER_PATH_INFO_, TYPE, OATPP_MACRO_UNFOLD_VA_ARGS PARAM_LIST) + +// QUERIES MACRO // ------------------------------------------------------ + +#define OATPP_MACRO_API_CONTROLLER_QUERIES(TYPE, PARAM_LIST) \ +TYPE OATPP_MACRO_FIRSTARG PARAM_LIST = __request->getQueryParameters(); + +#define OATPP_MACRO_API_CONTROLLER_QUERIES_INFO(TYPE, PARAM_LIST) + +// QUERY MACRO // ------------------------------------------------------ + +#define OATPP_MACRO_API_CONTROLLER_QUERY_1(TYPE, NAME) \ +auto __param_str_val_##NAME = __request->getQueryParameter(#NAME); \ +if(!__param_str_val_##NAME){ \ + return ApiController::handleError(Status::CODE_400, "Missing QUERY parameter '" #NAME "'"); \ +} \ +bool __param_validation_check_##NAME; \ +TYPE NAME = TYPE::Class::parseFromString(__param_str_val_##NAME, __param_validation_check_##NAME); \ +if(!__param_validation_check_##NAME){ \ + return ApiController::handleError(Status::CODE_400, "Invalid QUERY parameter '" #NAME "'. Expected type is '" #TYPE "'"); \ +} + +#define OATPP_MACRO_API_CONTROLLER_QUERY_2(TYPE, NAME, QUALIFIER) \ +auto __param_str_val_##NAME = __request->getQueryParameter(QUALIFIER); \ +if(!__param_str_val_##NAME){ \ + return ApiController::handleError(Status::CODE_400, \ + oatpp::String("Missing QUERY parameter '") + QUALIFIER + "'"); \ +} \ +bool __param_validation_check_##NAME; \ +TYPE NAME = TYPE::Class::parseFromString(__param_str_val_##NAME, __param_validation_check_##NAME); \ +if(!__param_validation_check_##NAME){ \ + return ApiController::handleError(Status::CODE_400, \ + oatpp::String("Invalid QUERY parameter '") + \ + QUALIFIER + \ + "'. Expected type is '" #TYPE "'"); \ +} + +#define OATPP_MACRO_API_CONTROLLER_QUERY(TYPE, PARAM_LIST) \ +OATPP_MACRO_API_CONTROLLER_MACRO_SELECTOR(OATPP_MACRO_API_CONTROLLER_QUERY_, TYPE, OATPP_MACRO_UNFOLD_VA_ARGS PARAM_LIST) + +// __INFO + +#define OATPP_MACRO_API_CONTROLLER_QUERY_INFO_1(TYPE, NAME) \ +info->queryParams.add(#NAME, TYPE::Class::getType()); + +#define OATPP_MACRO_API_CONTROLLER_QUERY_INFO_2(TYPE, NAME, QUALIFIER) \ +info->queryParams.add(QUALIFIER, TYPE::Class::getType()); + +#define OATPP_MACRO_API_CONTROLLER_QUERY_INFO(TYPE, PARAM_LIST) \ +OATPP_MACRO_API_CONTROLLER_MACRO_SELECTOR(OATPP_MACRO_API_CONTROLLER_QUERY_INFO_, TYPE, OATPP_MACRO_UNFOLD_VA_ARGS PARAM_LIST) + +// BODY_STRING MACRO // ------------------------------------------------------ + +#define OATPP_MACRO_API_CONTROLLER_BODY_STRING(TYPE, PARAM_LIST) \ +TYPE OATPP_MACRO_FIRSTARG PARAM_LIST = __request->readBodyToString(); + +// __INFO + +#define OATPP_MACRO_API_CONTROLLER_BODY_STRING_INFO(TYPE, PARAM_LIST) \ +info->body.name = OATPP_MACRO_FIRSTARG_STR PARAM_LIST; \ +info->body.type = oatpp::data::mapping::type::__class::String::getType(); + +// BODY_DTO MACRO // ------------------------------------------------------ + +#define OATPP_MACRO_API_CONTROLLER_BODY_DTO(TYPE, PARAM_LIST) \ +TYPE OATPP_MACRO_FIRSTARG PARAM_LIST; \ +__request->readBodyToDto(OATPP_MACRO_FIRSTARG PARAM_LIST, getDefaultObjectMapper().get()); \ +if(!OATPP_MACRO_FIRSTARG PARAM_LIST) { \ + return ApiController::handleError(Status::CODE_400, "Missing valid body parameter '" OATPP_MACRO_FIRSTARG_STR PARAM_LIST "'"); \ +} + +// __INFO + +#define OATPP_MACRO_API_CONTROLLER_BODY_DTO_INFO(TYPE, PARAM_LIST) \ +info->body.name = OATPP_MACRO_FIRSTARG_STR PARAM_LIST; \ +info->body.type = TYPE::Class::getType(); + +// FOR EACH // ------------------------------------------------------ + +#define OATPP_MACRO_API_CONTROLLER_FOR_EACH_PARAM_DECL_FIRST(INDEX, COUNT, X) \ +OATPP_MACRO_API_CONTROLLER_PARAM_TYPE X OATPP_MACRO_API_CONTROLLER_PARAM_NAME X + +#define OATPP_MACRO_API_CONTROLLER_FOR_EACH_PARAM_DECL_REST(INDEX, COUNT, X) \ +, OATPP_MACRO_API_CONTROLLER_PARAM_TYPE X OATPP_MACRO_API_CONTROLLER_PARAM_NAME X + +#define OATPP_MACRO_API_CONTROLLER_FOR_EACH_PARAM_PUT(INDEX, COUNT, X) \ +OATPP_MACRO_API_CONTROLLER_PARAM_MACRO X + +#define OATPP_MACRO_API_CONTROLLER_FOR_EACH_PARAM_CALL_FIRST(INDEX, COUNT, X) \ +OATPP_MACRO_API_CONTROLLER_PARAM_NAME X + +#define OATPP_MACRO_API_CONTROLLER_FOR_EACH_PARAM_CALL_REST(INDEX, COUNT, X) \ +, OATPP_MACRO_API_CONTROLLER_PARAM_NAME X + +#define OATPP_MACRO_API_CONTROLLER_FOR_EACH_PARAM_INFO(INDEX, COUNT, X) \ +OATPP_MACRO_API_CONTROLLER_PARAM_INFO X + +// ENDPOINT_INFO MACRO // ------------------------------------------------------ + +#define ENDPOINT_INFO(NAME) \ +\ +std::shared_ptr<Endpoint::Info> Z__ENDPOINT_CREATE_ADDITIONAL_INFO_##NAME() { \ + auto info = Z__EDNPOINT_INFO_GET_INSTANCE_##NAME(); \ + Z__ENDPOINT_ADD_INFO_##NAME(info); \ + return info; \ +} \ +\ +const std::shared_ptr<Endpoint::Info> Z__ENDPOINT_ADDITIONAL_INFO_##NAME = Z__ENDPOINT_CREATE_ADDITIONAL_INFO_##NAME(); \ +\ +void Z__ENDPOINT_ADD_INFO_##NAME(const std::shared_ptr<Endpoint::Info>& info) + +// ENDPOINT MACRO // ------------------------------------------------------ + +#define OATPP_MACRO_API_CONTROLLER_ENDPOINT_DECL_DEFAULTS(NAME, METHOD, PATH) \ +\ +template<class T> \ +static typename std::shared_ptr<Handler<T>> Z__ENDPOINT_HANDLER_GET_INSTANCE_##NAME(T* controller) { \ + auto handler = std::static_pointer_cast<Handler<T>>(controller->getEndpointHandler(#NAME)); \ + if(!handler) { \ + handler = Handler<T>::createShared(controller, &T::Z__PROXY_METHOD_##NAME, nullptr); \ + controller->setEndpointHandler(#NAME, handler); \ + } \ + return handler; \ +} \ +\ +std::shared_ptr<Endpoint::Info> Z__EDNPOINT_INFO_GET_INSTANCE_##NAME() { \ + std::shared_ptr<Endpoint::Info> info = getEndpointInfo(#NAME); \ + if(!info){ \ + info = Endpoint::Info::createShared(); \ + setEndpointInfo(#NAME, info); \ + } \ + return info; \ +} + +#define OATPP_MACRO_API_CONTROLLER_ENDPOINT_DECL_0(NAME, METHOD, PATH) \ +\ +EndpointInfoBuilder Z__CREATE_ENDPOINT_INFO_##NAME = [this](){ \ + auto info = Z__EDNPOINT_INFO_GET_INSTANCE_##NAME(); \ + info->name = #NAME; \ + info->path = PATH; \ + info->method = METHOD; \ + return info; \ +}; \ +\ +const std::shared_ptr<Endpoint> Z__ENDPOINT_##NAME = createEndpoint(m_endpoints, \ + Z__ENDPOINT_HANDLER_GET_INSTANCE_##NAME(this), \ + Z__CREATE_ENDPOINT_INFO_##NAME); + +#define OATPP_MACRO_API_CONTROLLER_ENDPOINT_0(NAME, METHOD, PATH) \ +OATPP_MACRO_API_CONTROLLER_ENDPOINT_DECL_DEFAULTS(NAME, METHOD, PATH) \ +OATPP_MACRO_API_CONTROLLER_ENDPOINT_DECL_0(NAME, METHOD, PATH) \ +\ +std::shared_ptr<oatpp::web::protocol::http::outgoing::Response> \ +Z__PROXY_METHOD_##NAME(const std::shared_ptr<oatpp::web::protocol::http::incoming::Request>& __request) \ +{ \ + (void)__request; \ + return NAME(); \ +} \ +\ +std::shared_ptr<oatpp::web::protocol::http::outgoing::Response> NAME() + +//////////////////// + +#define OATPP_MACRO_API_CONTROLLER_ENDPOINT_DECL_1(NAME, METHOD, PATH, ...) \ +\ +EndpointInfoBuilder Z__CREATE_ENDPOINT_INFO_##NAME = [this](){ \ +auto info = Z__EDNPOINT_INFO_GET_INSTANCE_##NAME(); \ + info->name = #NAME; \ + info->path = PATH; \ + info->method = METHOD; \ + OATPP_MACRO_FOREACH(OATPP_MACRO_API_CONTROLLER_FOR_EACH_PARAM_INFO, __VA_ARGS__) \ + return info; \ +}; \ +\ +const std::shared_ptr<Endpoint> Z__ENDPOINT_##NAME = createEndpoint(m_endpoints, \ + Z__ENDPOINT_HANDLER_GET_INSTANCE_##NAME(this), \ + Z__CREATE_ENDPOINT_INFO_##NAME); + +#define OATPP_MACRO_API_CONTROLLER_ENDPOINT_1(NAME, METHOD, PATH, ...) \ +OATPP_MACRO_API_CONTROLLER_ENDPOINT_DECL_DEFAULTS(NAME, METHOD, PATH) \ +OATPP_MACRO_API_CONTROLLER_ENDPOINT_DECL_1(NAME, METHOD, PATH, __VA_ARGS__) \ +\ +std::shared_ptr<oatpp::web::protocol::http::outgoing::Response> \ +Z__PROXY_METHOD_##NAME(const std::shared_ptr<oatpp::web::protocol::http::incoming::Request>& __request) \ +{ \ + OATPP_MACRO_FOREACH(OATPP_MACRO_API_CONTROLLER_FOR_EACH_PARAM_PUT, __VA_ARGS__) \ + return NAME( \ + OATPP_MACRO_FOREACH_FIRST_AND_REST( \ + OATPP_MACRO_API_CONTROLLER_FOR_EACH_PARAM_CALL_FIRST, \ + OATPP_MACRO_API_CONTROLLER_FOR_EACH_PARAM_CALL_REST, \ + __VA_ARGS__ \ + ) \ + ); \ +} \ +\ +std::shared_ptr<oatpp::web::protocol::http::outgoing::Response> NAME(\ + OATPP_MACRO_FOREACH_FIRST_AND_REST( \ + OATPP_MACRO_API_CONTROLLER_FOR_EACH_PARAM_DECL_FIRST, \ + OATPP_MACRO_API_CONTROLLER_FOR_EACH_PARAM_DECL_REST, \ + __VA_ARGS__ \ + ) \ +) + +// Chooser + +#define OATPP_MACRO_API_CONTROLLER_ENDPOINT_MACRO_0(METHOD, PATH, NAME) \ +OATPP_MACRO_EXPAND(OATPP_MACRO_API_CONTROLLER_ENDPOINT_0(NAME, METHOD, PATH)) + +#define OATPP_MACRO_API_CONTROLLER_ENDPOINT_MACRO_1(METHOD, PATH, NAME, ...) \ +OATPP_MACRO_EXPAND(OATPP_MACRO_API_CONTROLLER_ENDPOINT_1(NAME, METHOD, PATH, __VA_ARGS__)) + +/** + * Codegen macoro to be used in `oatpp::web::server::api::ApiController` to generate Endpoint. + * @param METHOD - Http method ("GET", "POST", "PUT", etc.). + * @param PATH - Path to endpoint (without host). + * @param NAME - Name of the generated method. + * @return - std::shared_ptr to &id:oatpp::web::protocol::http::outgoing::Response;. + */ +#define ENDPOINT(METHOD, PATH, ...) \ +OATPP_MACRO_EXPAND(OATPP_MACRO_MACRO_BINARY_SELECTOR(OATPP_MACRO_API_CONTROLLER_ENDPOINT_MACRO_, (__VA_ARGS__)) (METHOD, PATH, __VA_ARGS__)) + +/** + * Endpoint interceptor + */ +#define ENDPOINT_INTERCEPTOR(ENDPOINT_NAME, NAME) \ +\ +Handler<oatpp::web::server::api::ApiController>::Method \ + Z__INTERCEPTOR_METHOD_##ENDPOINT_NAME ##_ ##NAME = Z__INTERCEPTOR_METHOD_SET_##ENDPOINT_NAME ##_ ##NAME(this); \ +\ +template<class T> \ +Handler<oatpp::web::server::api::ApiController>::Method Z__INTERCEPTOR_METHOD_SET_##ENDPOINT_NAME ##_ ##NAME (T* controller) { \ + return static_cast<Handler<oatpp::web::server::api::ApiController>::Method>( \ + Z__ENDPOINT_HANDLER_GET_INSTANCE_##ENDPOINT_NAME(controller)->setMethod(&T::Z__PROXY_INTERCEPTOR_METHOD_##ENDPOINT_NAME ##_ ##NAME) \ + ); \ +} \ +\ +std::shared_ptr<oatpp::web::protocol::http::outgoing::Response> \ +Z__PROXY_INTERCEPTOR_METHOD_##ENDPOINT_NAME ##_ ##NAME(const std::shared_ptr<oatpp::web::protocol::http::incoming::Request>& request) { \ + return Z__USER_PROXY_INTERCEPTOR_METHOD_##ENDPOINT_NAME ##_ ##NAME(this, request); \ +} \ +\ +template<class T> \ +std::shared_ptr<oatpp::web::protocol::http::outgoing::Response> \ +Z__USER_PROXY_INTERCEPTOR_METHOD_##ENDPOINT_NAME ##_ ##NAME( \ + T* controller, \ + const std::shared_ptr<oatpp::web::protocol::http::incoming::Request>& request \ +) { \ + auto intercepted = static_cast<typename Handler<T>::Method>(Z__INTERCEPTOR_METHOD_##ENDPOINT_NAME ##_ ##NAME); \ + return Z__USER_INTERCEPTOR_METHOD_##ENDPOINT_NAME ##_ ##NAME <T> (intercepted, request); \ +} \ +\ +template<class T> \ +std::shared_ptr<oatpp::web::protocol::http::outgoing::Response> \ +Z__USER_INTERCEPTOR_METHOD_##ENDPOINT_NAME ##_ ##NAME( \ + typename Handler<T>::Method intercepted, \ + const std::shared_ptr<oatpp::web::protocol::http::incoming::Request>& request \ +) + +// ENDPOINT ASYNC MACRO // ------------------------------------------------------ + +/* + * 1 - Method to obtain endpoint call function ptr + * 2 - Endpoint info singleton + */ +#define OATPP_MACRO_API_CONTROLLER_ENDPOINT_ASYNC_DECL_DEFAULTS(NAME, METHOD, PATH) \ +\ +template<class T> \ +static typename std::shared_ptr<Handler<T>> Z__ENDPOINT_HANDLER_GET_INSTANCE_##NAME(T* controller) { \ + auto handler = std::static_pointer_cast<Handler<T>>(controller->getEndpointHandler(#NAME)); \ + if(!handler) { \ + handler = Handler<T>::createShared(controller, nullptr, &T::Z__PROXY_METHOD_##NAME); \ + controller->setEndpointHandler(#NAME, handler); \ + } \ + return handler; \ +} \ +\ +std::shared_ptr<Endpoint::Info> Z__EDNPOINT_INFO_GET_INSTANCE_##NAME() { \ + std::shared_ptr<Endpoint::Info> info = getEndpointInfo(#NAME); \ + if(!info){ \ + info = Endpoint::Info::createShared(); \ + setEndpointInfo(#NAME, info); \ + } \ + return info; \ +} + +/* + * 1 - Endpoint info instance + * 2 - Endpoint instance + */ +#define OATPP_MACRO_API_CONTROLLER_ENDPOINT_ASYNC_DECL(NAME, METHOD, PATH) \ +\ +EndpointInfoBuilder Z__CREATE_ENDPOINT_INFO_##NAME = [this](){ \ + auto info = Z__EDNPOINT_INFO_GET_INSTANCE_##NAME(); \ + info->name = #NAME; \ + info->path = PATH; \ + info->method = METHOD; \ + return info; \ +}; \ +\ +const std::shared_ptr<Endpoint> Z__ENDPOINT_##NAME = createEndpoint(m_endpoints, \ + Z__ENDPOINT_HANDLER_GET_INSTANCE_##NAME(this), \ + Z__CREATE_ENDPOINT_INFO_##NAME); + +/** + * Codegen macoro to be used in `oatpp::web::server::api::ApiController` to generate Asynchronous Endpoint. + * @param METHOD - Http method ("GET", "POST", "PUT", etc.). + * @param PATH - Path to endpoint (without host). + * @param NAME - Name of the generated method. + * @return - &id:oatpp::async::Action;. + */ +#define ENDPOINT_ASYNC(METHOD, PATH, NAME) \ +OATPP_MACRO_API_CONTROLLER_ENDPOINT_ASYNC_DECL_DEFAULTS(NAME, METHOD, PATH) \ +OATPP_MACRO_API_CONTROLLER_ENDPOINT_ASYNC_DECL(NAME, METHOD, PATH) \ +\ +oatpp::async::CoroutineStarterForResult<const std::shared_ptr<oatpp::web::protocol::http::outgoing::Response>&> \ +Z__PROXY_METHOD_##NAME(const std::shared_ptr<oatpp::web::protocol::http::incoming::Request>& __request) \ +{ \ + return NAME::startForResult(this, __request); \ +} \ +\ +class NAME : public HandlerCoroutine<NAME, __ControllerType> + +/** + * Auxiliary codegen macro for `ENDPOINT_ASYNC` to generate correct constructor for Asynchronous Endpoint Coroutine. + * @NAME - Name of the endpoint. Exact the same name as was passed to `ENDPOINT_ASYNC` macro. + */ +#define ENDPOINT_ASYNC_INIT(NAME) \ +public: \ +\ + NAME(__ControllerType* pController, \ + const std::shared_ptr<IncomingRequest>& pRequest) \ + : HandlerCoroutine(pController, pRequest) \ + {} + + +/** + * Endpoint interceptor + */ +#define ENDPOINT_INTERCEPTOR_ASYNC(ENDPOINT_NAME, NAME) \ +\ +Handler<oatpp::web::server::api::ApiController>::MethodAsync \ + Z__INTERCEPTOR_METHOD_##ENDPOINT_NAME ##_ ##NAME = Z__INTERCEPTOR_METHOD_SET_##ENDPOINT_NAME ##_ ##NAME(this); \ +\ +template<class T> \ +Handler<oatpp::web::server::api::ApiController>::MethodAsync Z__INTERCEPTOR_METHOD_SET_##ENDPOINT_NAME ##_ ##NAME (T* controller) { \ + return static_cast<Handler<oatpp::web::server::api::ApiController>::MethodAsync>( \ + Z__ENDPOINT_HANDLER_GET_INSTANCE_##ENDPOINT_NAME(controller)->setMethodAsync(&T::Z__PROXY_INTERCEPTOR_METHOD_##ENDPOINT_NAME ##_ ##NAME) \ + ); \ +} \ +\ +oatpp::async::CoroutineStarterForResult<const std::shared_ptr<oatpp::web::protocol::http::outgoing::Response>&> \ +Z__PROXY_INTERCEPTOR_METHOD_##ENDPOINT_NAME ##_ ##NAME(const std::shared_ptr<oatpp::web::protocol::http::incoming::Request>& request) { \ + return Z__USER_PROXY_INTERCEPTOR_METHOD_##ENDPOINT_NAME ##_ ##NAME(this, request); \ +} \ +\ +template<class T> \ +oatpp::async::CoroutineStarterForResult<const std::shared_ptr<oatpp::web::protocol::http::outgoing::Response>&> \ +Z__USER_PROXY_INTERCEPTOR_METHOD_##ENDPOINT_NAME ##_ ##NAME( \ + T* controller, \ + const std::shared_ptr<oatpp::web::protocol::http::incoming::Request>& request \ +) { \ + auto intercepted = static_cast<typename Handler<T>::MethodAsync>(Z__INTERCEPTOR_METHOD_##ENDPOINT_NAME ##_ ##NAME); \ + return Z__USER_INTERCEPTOR_METHOD_##ENDPOINT_NAME ##_ ##NAME <T> (intercepted, request); \ +} \ +\ +template<class T> \ +oatpp::async::CoroutineStarterForResult<const std::shared_ptr<oatpp::web::protocol::http::outgoing::Response>&> \ +Z__USER_INTERCEPTOR_METHOD_##ENDPOINT_NAME ##_ ##NAME( \ + typename Handler<T>::MethodAsync intercepted, \ + const std::shared_ptr<oatpp::web::protocol::http::incoming::Request>& request \ +) diff --git a/src/oatpp/codegen/api_controller/base_undef.hpp b/src/oatpp/codegen/api_controller/base_undef.hpp new file mode 100644 index 00000000..b4d8f1b7 --- /dev/null +++ b/src/oatpp/codegen/api_controller/base_undef.hpp @@ -0,0 +1,144 @@ +/*************************************************************************** + * + * Project _____ __ ____ _ _ + * ( _ ) /__\ (_ _)_| |_ _| |_ + * )(_)( /(__)\ )( (_ _)(_ _) + * (_____)(__)(__)(__) |_| |_| + * + * + * Copyright 2018-present, Leonid Stryzhevskyi <lganzzzo@gmail.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************/ + +#undef OATPP_MACRO_API_CONTROLLER_PARAM_MACRO +#undef OATPP_MACRO_API_CONTROLLER_PARAM_INFO +#undef OATPP_MACRO_API_CONTROLLER_PARAM_TYPE +#undef OATPP_MACRO_API_CONTROLLER_PARAM_NAME +#undef OATPP_MACRO_API_CONTROLLER_PARAM_TYPE_STR +#undef OATPP_MACRO_API_CONTROLLER_PARAM_NAME_STR +#undef OATPP_MACRO_API_CONTROLLER_PARAM + +#undef REQUEST +#undef HEADER +#undef PATH +#undef QUERIES +#undef QUERY +#undef BODY_STRING +#undef BODY_DTO + +// INIT // ------------------------------------------------------ + +#undef REST_CONTROLLER_INIT + +#undef OATPP_MACRO_API_CONTROLLER_MACRO_SELECTOR + +// REQUEST MACRO // ------------------------------------------------------ + +#undef OATPP_MACRO_API_CONTROLLER_REQUEST +#undef OATPP_MACRO_API_CONTROLLER_REQUEST_INFO + +// HEADER MACRO // ------------------------------------------------------ + +#undef OATPP_MACRO_API_CONTROLLER_HEADER_1 +#undef OATPP_MACRO_API_CONTROLLER_HEADER_2 +#undef OATPP_MACRO_API_CONTROLLER_HEADER + +// __INFO + +#undef OATPP_MACRO_API_CONTROLLER_HEADER_INFO_1 +#undef OATPP_MACRO_API_CONTROLLER_HEADER_INFO_2 +#undef OATPP_MACRO_API_CONTROLLER_HEADER_INFO + +// PATH MACRO // ------------------------------------------------------ + +#undef OATPP_MACRO_API_CONTROLLER_PATH_1 +#undef OATPP_MACRO_API_CONTROLLER_PATH_2 +#undef OATPP_MACRO_API_CONTROLLER_PATH + +// __INFO + +#undef OATPP_MACRO_API_CONTROLLER_PATH_INFO_1 +#undef OATPP_MACRO_API_CONTROLLER_PATH_INFO_2 +#undef OATPP_MACRO_API_CONTROLLER_PATH_INFO + +// QUERIES MACRO // ------------------------------------------------------ + +#undef OATPP_MACRO_API_CONTROLLER_QUERIES +#undef OATPP_MACRO_API_CONTROLLER_QUERIES_INFO + +// QUERY MACRO // ------------------------------------------------------ + +#undef OATPP_MACRO_API_CONTROLLER_QUERY_1 +#undef OATPP_MACRO_API_CONTROLLER_QUERY_2 +#undef OATPP_MACRO_API_CONTROLLER_QUERY + +// __INFO + +#undef OATPP_MACRO_API_CONTROLLER_QUERY_INFO_1 +#undef OATPP_MACRO_API_CONTROLLER_QUERY_INFO_2 +#undef OATPP_MACRO_API_CONTROLLER_QUERY_INFO + +// BODY_STRING MACRO // ------------------------------------------------------ + +#undef OATPP_MACRO_API_CONTROLLER_BODY_STRING + +// __INFO + +#undef OATPP_MACRO_API_CONTROLLER_BODY_STRING_INFO + +// BODY_DTO MACRO // ------------------------------------------------------ + +#undef OATPP_MACRO_API_CONTROLLER_BODY_DTO + +// __INFO + +#undef OATPP_MACRO_API_CONTROLLER_BODY_DTO_INFO + +// FOR EACH // ------------------------------------------------------ + +#undef OATPP_MACRO_API_CONTROLLER_FOR_EACH_PARAM_DECL +#undef OATPP_MACRO_API_CONTROLLER_FOR_EACH_PARAM_PUT +#undef OATPP_MACRO_API_CONTROLLER_FOR_EACH_PARAM_CALL +#undef OATPP_MACRO_API_CONTROLLER_FOR_EACH_PARAM_INFO + +// ENDPOINT_INFO MACRO // ------------------------------------------------------ + +#undef ENDPOINT_INFO + +// ENDPOINT MACRO // ------------------------------------------------------ + +#undef OATPP_MACRO_API_CONTROLLER_ENDPOINT_DECL_DEFAULTS + +#undef OATPP_MACRO_API_CONTROLLER_ENDPOINT_DECL_0 +#undef OATPP_MACRO_API_CONTROLLER_ENDPOINT_0 + +#undef OATPP_MACRO_API_CONTROLLER_ENDPOINT_DECL_1 +#undef OATPP_MACRO_API_CONTROLLER_ENDPOINT_1 + +#undef OATPP_MACRO_API_CONTROLLER_ENDPOINT_MACRO_0 +#undef OATPP_MACRO_API_CONTROLLER_ENDPOINT_MACRO_1 + +#undef ENDPOINT + +#undef ENDPOINT_INTERCEPTOR + +// ENDPOINT ASYNC MACRO // ------------------------------------------------------ + +#undef OATPP_MACRO_API_CONTROLLER_ENDPOINT_ASYNC_DECL_DEFAULTS +#undef OATPP_MACRO_API_CONTROLLER_ENDPOINT_ASYNC_DECL +#undef ENDPOINT_ASYNC +#undef ENDPOINT_ASYNC_INIT + +#undef ENDPOINT_INTERCEPTOR_ASYNC diff --git a/src/oatpp/codegen/codegen_define_ApiController_.hpp b/src/oatpp/codegen/codegen_define_ApiController_.hpp index 22aeee29..fbb58953 100644 --- a/src/oatpp/codegen/codegen_define_ApiController_.hpp +++ b/src/oatpp/codegen/codegen_define_ApiController_.hpp @@ -45,488 +45,8 @@ #include "oatpp/core/macro/basic.hpp" #include "oatpp/core/macro/codegen.hpp" -#define OATPP_MACRO_API_CONTROLLER_PARAM_MACRO(MACRO, INFO, TYPE, PARAM_LIST) MACRO(TYPE, PARAM_LIST) -#define OATPP_MACRO_API_CONTROLLER_PARAM_INFO(MACRO, INFO, TYPE, PARAM_LIST) INFO(TYPE, PARAM_LIST) -#define OATPP_MACRO_API_CONTROLLER_PARAM_TYPE(MACRO, INFO, TYPE, PARAM_LIST) TYPE -#define OATPP_MACRO_API_CONTROLLER_PARAM_NAME(MACRO, INFO, TYPE, PARAM_LIST) OATPP_MACRO_FIRSTARG PARAM_LIST -#define OATPP_MACRO_API_CONTROLLER_PARAM_TYPE_STR(MACRO, INFO, TYPE, PARAM_LIST) #TYPE -#define OATPP_MACRO_API_CONTROLLER_PARAM_NAME_STR(MACRO, INFO, TYPE, PARAM_LIST) OATPP_MACRO_FIRSTARG_STR PARAM_LIST -#define OATPP_MACRO_API_CONTROLLER_PARAM(MACRO, INFO, TYPE, PARAM_LIST) (MACRO, INFO, TYPE, PARAM_LIST) - -#define REQUEST(TYPE, ...) \ -OATPP_MACRO_API_CONTROLLER_PARAM(OATPP_MACRO_API_CONTROLLER_REQUEST, OATPP_MACRO_API_CONTROLLER_REQUEST_INFO, TYPE, (__VA_ARGS__)) - -#define HEADER(TYPE, ...) \ -OATPP_MACRO_API_CONTROLLER_PARAM(OATPP_MACRO_API_CONTROLLER_HEADER, OATPP_MACRO_API_CONTROLLER_HEADER_INFO, TYPE, (__VA_ARGS__)) - -#define PATH(TYPE, ...) \ -OATPP_MACRO_API_CONTROLLER_PARAM(OATPP_MACRO_API_CONTROLLER_PATH, OATPP_MACRO_API_CONTROLLER_PATH_INFO, TYPE, (__VA_ARGS__)) - -#define QUERIES(TYPE, ...) \ -OATPP_MACRO_API_CONTROLLER_PARAM(OATPP_MACRO_API_CONTROLLER_QUERIES, OATPP_MACRO_API_CONTROLLER_QUERIES_INFO, TYPE, (__VA_ARGS__)) - -#define QUERY(TYPE, ...) \ -OATPP_MACRO_API_CONTROLLER_PARAM(OATPP_MACRO_API_CONTROLLER_QUERY, OATPP_MACRO_API_CONTROLLER_QUERY_INFO, TYPE, (__VA_ARGS__)) - -#define BODY_STRING(TYPE, ...) \ -OATPP_MACRO_API_CONTROLLER_PARAM(OATPP_MACRO_API_CONTROLLER_BODY_STRING, OATPP_MACRO_API_CONTROLLER_BODY_STRING_INFO, TYPE, (__VA_ARGS__)) - -#define BODY_DTO(TYPE, ...) \ -OATPP_MACRO_API_CONTROLLER_PARAM(OATPP_MACRO_API_CONTROLLER_BODY_DTO, OATPP_MACRO_API_CONTROLLER_BODY_DTO_INFO, TYPE, (__VA_ARGS__)) - -#define AUTHORIZATION(TYPE, ...) \ -OATPP_MACRO_API_CONTROLLER_PARAM(OATPP_MACRO_API_CONTROLLER_AUTHORIZATION, OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_INFO, TYPE, (__VA_ARGS__)) - -////////////////////////////////////////////////////////////////////////// - -#define OATPP_MACRO_API_CONTROLLER_MACRO_SELECTOR(MACRO, TYPE, ...) \ -OATPP_MACRO_EXPAND(OATPP_MACRO_MACRO_SELECTOR(MACRO, (__VA_ARGS__)) (TYPE, __VA_ARGS__)) - -////////////////////////////////////////////////////////////////////////// - -// REQUEST MACRO // ------------------------------------------------------ - -#define OATPP_MACRO_API_CONTROLLER_REQUEST(TYPE, PARAM_LIST) \ -TYPE OATPP_MACRO_FIRSTARG PARAM_LIST = __request; - -#define OATPP_MACRO_API_CONTROLLER_REQUEST_INFO(TYPE, PARAM_LIST) - - -// HEADER MACRO // ------------------------------------------------------ - -#define OATPP_MACRO_API_CONTROLLER_HEADER_1(TYPE, NAME) \ -auto __param_str_val_##NAME = __request->getHeader(#NAME); \ -if(!__param_str_val_##NAME){ \ - return ApiController::handleError(Status::CODE_400, "Missing HEADER parameter '" #NAME "'"); \ -} \ -bool __param_validation_check_##NAME; \ -TYPE NAME = TYPE::Class::parseFromString(__param_str_val_##NAME, __param_validation_check_##NAME); \ -if(!__param_validation_check_##NAME){ \ - return ApiController::handleError(Status::CODE_400, "Invalid HEADER parameter '" #NAME "'. Expected type is '" #TYPE "'"); \ -} - -#define OATPP_MACRO_API_CONTROLLER_HEADER_2(TYPE, NAME, QUALIFIER) \ -auto __param_str_val_##NAME = __request->getHeader(QUALIFIER); \ -if(!__param_str_val_##NAME){ \ - return ApiController::handleError(Status::CODE_400, \ - oatpp::String("Missing HEADER parameter '") + QUALIFIER + "'"); \ -} \ -bool __param_validation_check_##NAME; \ -TYPE NAME = TYPE::Class::parseFromString(__param_str_val_##NAME, __param_validation_check_##NAME); \ -if(!__param_validation_check_##NAME){ \ - return ApiController::handleError(Status::CODE_400, \ - oatpp::String("Invalid HEADER parameter '") + \ - QUALIFIER + \ - "'. Expected type is '" #TYPE "'"); \ -} - -#define OATPP_MACRO_API_CONTROLLER_HEADER(TYPE, PARAM_LIST) \ -OATPP_MACRO_API_CONTROLLER_MACRO_SELECTOR(OATPP_MACRO_API_CONTROLLER_HEADER_, TYPE, OATPP_MACRO_UNFOLD_VA_ARGS PARAM_LIST) - -// __INFO - -#define OATPP_MACRO_API_CONTROLLER_HEADER_INFO_1(TYPE, NAME) \ -info->headers.add(#NAME, TYPE::Class::getType()); - -#define OATPP_MACRO_API_CONTROLLER_HEADER_INFO_2(TYPE, NAME, QUALIFIER) \ -info->headers.add(QUALIFIER, TYPE::Class::getType()); - -#define OATPP_MACRO_API_CONTROLLER_HEADER_INFO(TYPE, PARAM_LIST) \ -OATPP_MACRO_API_CONTROLLER_MACRO_SELECTOR(OATPP_MACRO_API_CONTROLLER_HEADER_INFO_, TYPE, OATPP_MACRO_UNFOLD_VA_ARGS PARAM_LIST) - - -// PATH MACRO // ------------------------------------------------------ - -#define OATPP_MACRO_API_CONTROLLER_PATH_1(TYPE, NAME) \ -auto __param_str_val_##NAME = __request->getPathVariable(#NAME); \ -if(!__param_str_val_##NAME){ \ - return ApiController::handleError(Status::CODE_400, "Missing PATH parameter '" #NAME "'"); \ -} \ -bool __param_validation_check_##NAME; \ -TYPE NAME = TYPE::Class::parseFromString(__param_str_val_##NAME, __param_validation_check_##NAME); \ -if(!__param_validation_check_##NAME){ \ - return ApiController::handleError(Status::CODE_400, "Invalid PATH parameter '" #NAME "'. Expected type is '" #TYPE "'"); \ -} - -#define OATPP_MACRO_API_CONTROLLER_PATH_2(TYPE, NAME, QUALIFIER) \ -auto __param_str_val_##NAME = __request->getPathVariable(QUALIFIER); \ -if(!__param_str_val_##NAME){ \ - return ApiController::handleError(Status::CODE_400, \ - oatpp::String("Missing PATH parameter '") + QUALIFIER + "'"); \ -} \ -bool __param_validation_check_##NAME; \ -TYPE NAME = TYPE::Class::parseFromString(__param_str_val_##NAME, __param_validation_check_##NAME); \ -if(!__param_validation_check_##NAME){ \ - return ApiController::handleError(Status::CODE_400, \ - oatpp::String("Invalid PATH parameter '") + \ - QUALIFIER + \ - "'. Expected type is '" #TYPE "'"); \ -} - -#define OATPP_MACRO_API_CONTROLLER_PATH(TYPE, PARAM_LIST) \ -OATPP_MACRO_API_CONTROLLER_MACRO_SELECTOR(OATPP_MACRO_API_CONTROLLER_PATH_, TYPE, OATPP_MACRO_UNFOLD_VA_ARGS PARAM_LIST) - -// __INFO - -#define OATPP_MACRO_API_CONTROLLER_PATH_INFO_1(TYPE, NAME) \ -info->pathParams.add(#NAME, TYPE::Class::getType()); - -#define OATPP_MACRO_API_CONTROLLER_PATH_INFO_2(TYPE, NAME, QUALIFIER) \ -info->pathParams.add(QUALIFIER, TYPE::Class::getType()); - -#define OATPP_MACRO_API_CONTROLLER_PATH_INFO(TYPE, PARAM_LIST) \ -OATPP_MACRO_API_CONTROLLER_MACRO_SELECTOR(OATPP_MACRO_API_CONTROLLER_PATH_INFO_, TYPE, OATPP_MACRO_UNFOLD_VA_ARGS PARAM_LIST) - -// QUERIES MACRO // ------------------------------------------------------ - -#define OATPP_MACRO_API_CONTROLLER_QUERIES(TYPE, PARAM_LIST) \ -TYPE OATPP_MACRO_FIRSTARG PARAM_LIST = __request->getQueryParameters(); - -#define OATPP_MACRO_API_CONTROLLER_QUERIES_INFO(TYPE, PARAM_LIST) - -// QUERY MACRO // ------------------------------------------------------ - -#define OATPP_MACRO_API_CONTROLLER_QUERY_1(TYPE, NAME) \ -auto __param_str_val_##NAME = __request->getQueryParameter(#NAME); \ -if(!__param_str_val_##NAME){ \ - return ApiController::handleError(Status::CODE_400, "Missing QUERY parameter '" #NAME "'"); \ -} \ -bool __param_validation_check_##NAME; \ -TYPE NAME = TYPE::Class::parseFromString(__param_str_val_##NAME, __param_validation_check_##NAME); \ -if(!__param_validation_check_##NAME){ \ - return ApiController::handleError(Status::CODE_400, "Invalid QUERY parameter '" #NAME "'. Expected type is '" #TYPE "'"); \ -} - -#define OATPP_MACRO_API_CONTROLLER_QUERY_2(TYPE, NAME, QUALIFIER) \ -auto __param_str_val_##NAME = __request->getQueryParameter(QUALIFIER); \ -if(!__param_str_val_##NAME){ \ - return ApiController::handleError(Status::CODE_400, \ - oatpp::String("Missing QUERY parameter '") + QUALIFIER + "'"); \ -} \ -bool __param_validation_check_##NAME; \ -TYPE NAME = TYPE::Class::parseFromString(__param_str_val_##NAME, __param_validation_check_##NAME); \ -if(!__param_validation_check_##NAME){ \ - return ApiController::handleError(Status::CODE_400, \ - oatpp::String("Invalid QUERY parameter '") + \ - QUALIFIER + \ - "'. Expected type is '" #TYPE "'"); \ -} - -#define OATPP_MACRO_API_CONTROLLER_QUERY(TYPE, PARAM_LIST) \ -OATPP_MACRO_API_CONTROLLER_MACRO_SELECTOR(OATPP_MACRO_API_CONTROLLER_QUERY_, TYPE, OATPP_MACRO_UNFOLD_VA_ARGS PARAM_LIST) - -// __INFO - -#define OATPP_MACRO_API_CONTROLLER_QUERY_INFO_1(TYPE, NAME) \ -info->queryParams.add(#NAME, TYPE::Class::getType()); - -#define OATPP_MACRO_API_CONTROLLER_QUERY_INFO_2(TYPE, NAME, QUALIFIER) \ -info->queryParams.add(QUALIFIER, TYPE::Class::getType()); - -#define OATPP_MACRO_API_CONTROLLER_QUERY_INFO(TYPE, PARAM_LIST) \ -OATPP_MACRO_API_CONTROLLER_MACRO_SELECTOR(OATPP_MACRO_API_CONTROLLER_QUERY_INFO_, TYPE, OATPP_MACRO_UNFOLD_VA_ARGS PARAM_LIST) - -// BODY_STRING MACRO // ------------------------------------------------------ - -#define OATPP_MACRO_API_CONTROLLER_BODY_STRING(TYPE, PARAM_LIST) \ -TYPE OATPP_MACRO_FIRSTARG PARAM_LIST = __request->readBodyToString(); - -// __INFO - -#define OATPP_MACRO_API_CONTROLLER_BODY_STRING_INFO(TYPE, PARAM_LIST) \ -info->body.name = OATPP_MACRO_FIRSTARG_STR PARAM_LIST; \ -info->body.type = oatpp::data::mapping::type::__class::String::getType(); - -// BODY_DTO MACRO // ------------------------------------------------------ - -#define OATPP_MACRO_API_CONTROLLER_BODY_DTO(TYPE, PARAM_LIST) \ -TYPE OATPP_MACRO_FIRSTARG PARAM_LIST; \ -__request->readBodyToDto(OATPP_MACRO_FIRSTARG PARAM_LIST, getDefaultObjectMapper().get()); \ -if(!OATPP_MACRO_FIRSTARG PARAM_LIST) { \ - return ApiController::handleError(Status::CODE_400, "Missing valid body parameter '" OATPP_MACRO_FIRSTARG_STR PARAM_LIST "'"); \ -} - -// __INFO - -#define OATPP_MACRO_API_CONTROLLER_BODY_DTO_INFO(TYPE, PARAM_LIST) \ -info->body.name = OATPP_MACRO_FIRSTARG_STR PARAM_LIST; \ -info->body.type = TYPE::Class::getType(); - -// AUTHORIZATION MACRO // ------------------------------------------------------ - -#define OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_1(TYPE, NAME) \ -auto __param_str_val_##NAME = __request->getHeader(oatpp::web::protocol::http::Header::AUTHORIZATION); \ -std::shared_ptr<oatpp::web::server::handler::AuthorizationObject> __param_aosp_val_##NAME = ApiController::handleDefaultAuthorization(__param_str_val_##NAME); \ -TYPE NAME = std::static_pointer_cast<TYPE::element_type>(__param_aosp_val_##NAME); - -#define OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_2(TYPE, NAME, AUTH_HANDLER) \ -auto __param_str_val_##NAME = __request->getHeader(oatpp::web::protocol::http::Header::AUTHORIZATION); \ -std::shared_ptr<oatpp::web::server::handler::AuthorizationHandler> __auth_handler_##NAME = AUTH_HANDLER; \ -std::shared_ptr<oatpp::web::server::handler::AuthorizationObject> __param_aosp_val_##NAME = __auth_handler_##NAME->handleAuthorization(__param_str_val_##NAME); \ -TYPE NAME = std::static_pointer_cast<TYPE::element_type>(__param_aosp_val_##NAME); - -#define OATPP_MACRO_API_CONTROLLER_AUTHORIZATION(TYPE, PARAM_LIST) \ -OATPP_MACRO_API_CONTROLLER_MACRO_SELECTOR(OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_, TYPE, OATPP_MACRO_UNFOLD_VA_ARGS PARAM_LIST) - -// __INFO - -#define OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_INFO_1(TYPE, NAME) \ -auto __param_obj_##NAME = ApiController::getDefaultAuthorizationHandler(); \ -if(__param_obj_##NAME) { \ - info->headers.add(oatpp::web::protocol::http::Header::AUTHORIZATION, oatpp::String::Class::getType()); \ - info->headers[oatpp::web::protocol::http::Header::AUTHORIZATION].description = __param_obj_##NAME ->getScheme(); \ - info->authorization = __param_obj_##NAME ->getScheme(); \ -} else { \ - throw oatpp::web::protocol::http::HttpError(Status::CODE_500, "No authorization handler set up in controller before controller was added to router or swagger-doc."); \ -} - -#define OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_INFO_2(TYPE, NAME, AUTH_HANDLER) \ -std::shared_ptr<oatpp::web::server::handler::AuthorizationHandler> __auth_handler_##NAME = AUTH_HANDLER; \ -if(__auth_handler_##NAME) { \ - info->headers.add(oatpp::web::protocol::http::Header::AUTHORIZATION, oatpp::String::Class::getType()); \ - info->headers[oatpp::web::protocol::http::Header::AUTHORIZATION].description = __auth_handler_##NAME->getScheme(); \ - info->authorization = __auth_handler_##NAME->getScheme(); \ -} else { \ - throw oatpp::web::protocol::http::HttpError(Status::CODE_500, "Invalid authorization handler given (or not set up) in AUTHORIZATION(TYPE, NAME, AUTH_HANDLER) before controller was added to router or swagger-doc."); \ -} - -#define OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_INFO(TYPE, PARAM_LIST) \ -OATPP_MACRO_API_CONTROLLER_MACRO_SELECTOR(OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_INFO_, TYPE, OATPP_MACRO_UNFOLD_VA_ARGS PARAM_LIST) - -// FOR EACH // ------------------------------------------------------ - -#define OATPP_MACRO_API_CONTROLLER_FOR_EACH_PARAM_DECL_FIRST(INDEX, COUNT, X) \ -OATPP_MACRO_API_CONTROLLER_PARAM_TYPE X OATPP_MACRO_API_CONTROLLER_PARAM_NAME X - -#define OATPP_MACRO_API_CONTROLLER_FOR_EACH_PARAM_DECL_REST(INDEX, COUNT, X) \ -, OATPP_MACRO_API_CONTROLLER_PARAM_TYPE X OATPP_MACRO_API_CONTROLLER_PARAM_NAME X - -#define OATPP_MACRO_API_CONTROLLER_FOR_EACH_PARAM_PUT(INDEX, COUNT, X) \ -OATPP_MACRO_API_CONTROLLER_PARAM_MACRO X - -#define OATPP_MACRO_API_CONTROLLER_FOR_EACH_PARAM_CALL_FIRST(INDEX, COUNT, X) \ -OATPP_MACRO_API_CONTROLLER_PARAM_NAME X - -#define OATPP_MACRO_API_CONTROLLER_FOR_EACH_PARAM_CALL_REST(INDEX, COUNT, X) \ -, OATPP_MACRO_API_CONTROLLER_PARAM_NAME X - -#define OATPP_MACRO_API_CONTROLLER_FOR_EACH_PARAM_INFO(INDEX, COUNT, X) \ -OATPP_MACRO_API_CONTROLLER_PARAM_INFO X - -// ENDPOINT_INFO MACRO // ------------------------------------------------------ - -#define ENDPOINT_INFO(NAME) \ -\ -std::shared_ptr<Endpoint::Info> Z__ENDPOINT_CREATE_ADDITIONAL_INFO_##NAME() { \ - auto info = Z__EDNPOINT_INFO_GET_INSTANCE_##NAME(); \ - Z__ENDPOINT_ADD_INFO_##NAME(info); \ - return info; \ -} \ -\ -const std::shared_ptr<Endpoint::Info> Z__ENDPOINT_ADDITIONAL_INFO_##NAME = Z__ENDPOINT_CREATE_ADDITIONAL_INFO_##NAME(); \ -\ -void Z__ENDPOINT_ADD_INFO_##NAME(const std::shared_ptr<Endpoint::Info>& info) - -// ENDPOINT MACRO // ------------------------------------------------------ - -#define OATPP_MACRO_API_CONTROLLER_ENDPOINT_DECL_DEFAULTS(NAME, METHOD, PATH) \ -\ -template<class T> \ -static typename Handler<T>::Method Z__ENDPOINT_METHOD_##NAME(T* controller) { \ - (void)controller; \ - return &T::Z__PROXY_METHOD_##NAME; \ -} \ -\ -std::shared_ptr<Endpoint::Info> Z__EDNPOINT_INFO_GET_INSTANCE_##NAME() { \ - std::shared_ptr<Endpoint::Info> info = getEndpointInfo(#NAME); \ - if(!info){ \ - info = Endpoint::Info::createShared(); \ - setEndpointInfo(#NAME, info); \ - } \ - return info; \ -} - -#define OATPP_MACRO_API_CONTROLLER_ENDPOINT_DECL_0(NAME, METHOD, PATH) \ -\ -EndpointInfoBuilder Z__CREATE_ENDPOINT_INFO_##NAME = [this](){ \ - auto info = Z__EDNPOINT_INFO_GET_INSTANCE_##NAME(); \ - info->name = #NAME; \ - info->path = PATH; \ - info->method = METHOD; \ - return info; \ -}; \ -\ -const std::shared_ptr<Endpoint> Z__ENDPOINT_##NAME = createEndpoint(m_endpoints, \ - this, \ - Z__ENDPOINT_METHOD_##NAME(this), \ - nullptr, \ - Z__CREATE_ENDPOINT_INFO_##NAME); - -#define OATPP_MACRO_API_CONTROLLER_ENDPOINT_0(NAME, METHOD, PATH) \ -OATPP_MACRO_API_CONTROLLER_ENDPOINT_DECL_DEFAULTS(NAME, METHOD, PATH) \ -OATPP_MACRO_API_CONTROLLER_ENDPOINT_DECL_0(NAME, METHOD, PATH) \ -\ -std::shared_ptr<oatpp::web::protocol::http::outgoing::Response> \ -Z__PROXY_METHOD_##NAME(const std::shared_ptr<oatpp::web::protocol::http::incoming::Request>& __request) \ -{ \ - (void)__request; \ - auto resp = NAME(); \ - auto interceptors = m_interceptors->find(#NAME); \ - if(interceptors != nullptr) { \ - auto interceptor = interceptors->getValue()->getFirstNode(); \ - while(interceptor != nullptr) { \ - resp = interceptor->getData()->operator()(resp); \ - interceptor = interceptor->getNext(); \ - } \ - } \ - return resp; \ -} \ -\ -std::shared_ptr<oatpp::web::protocol::http::outgoing::Response> NAME() - -//////////////////// - -#define OATPP_MACRO_API_CONTROLLER_ENDPOINT_DECL_1(NAME, METHOD, PATH, ...) \ -\ -EndpointInfoBuilder Z__CREATE_ENDPOINT_INFO_##NAME = [this](){ \ -auto info = Z__EDNPOINT_INFO_GET_INSTANCE_##NAME(); \ - info->name = #NAME; \ - info->path = PATH; \ - info->method = METHOD; \ - OATPP_MACRO_FOREACH(OATPP_MACRO_API_CONTROLLER_FOR_EACH_PARAM_INFO, __VA_ARGS__) \ - return info; \ -}; \ -\ -const std::shared_ptr<Endpoint> Z__ENDPOINT_##NAME = createEndpoint(m_endpoints, \ - this, \ - Z__ENDPOINT_METHOD_##NAME(this), \ - nullptr, \ - Z__CREATE_ENDPOINT_INFO_##NAME); - -#define OATPP_MACRO_API_CONTROLLER_ENDPOINT_1(NAME, METHOD, PATH, ...) \ -OATPP_MACRO_API_CONTROLLER_ENDPOINT_DECL_DEFAULTS(NAME, METHOD, PATH) \ -OATPP_MACRO_API_CONTROLLER_ENDPOINT_DECL_1(NAME, METHOD, PATH, __VA_ARGS__) \ -\ -std::shared_ptr<oatpp::web::protocol::http::outgoing::Response> \ -Z__PROXY_METHOD_##NAME(const std::shared_ptr<oatpp::web::protocol::http::incoming::Request>& __request) \ -{ \ - OATPP_MACRO_FOREACH(OATPP_MACRO_API_CONTROLLER_FOR_EACH_PARAM_PUT, __VA_ARGS__) \ - auto resp = NAME( \ - OATPP_MACRO_FOREACH_FIRST_AND_REST( \ - OATPP_MACRO_API_CONTROLLER_FOR_EACH_PARAM_CALL_FIRST, \ - OATPP_MACRO_API_CONTROLLER_FOR_EACH_PARAM_CALL_REST, \ - __VA_ARGS__ \ - ) \ - ); \ - auto interceptors = m_interceptors->find(#NAME); \ - if(interceptors != nullptr) { \ - auto interceptor = interceptors->getValue()->getFirstNode(); \ - while(interceptor != nullptr) { \ - resp = interceptor->getData()->operator()(resp); \ - interceptor = interceptor->getNext(); \ - } \ - } \ - return resp; \ -} \ -\ -std::shared_ptr<oatpp::web::protocol::http::outgoing::Response> NAME(\ - OATPP_MACRO_FOREACH_FIRST_AND_REST( \ - OATPP_MACRO_API_CONTROLLER_FOR_EACH_PARAM_DECL_FIRST, \ - OATPP_MACRO_API_CONTROLLER_FOR_EACH_PARAM_DECL_REST, \ - __VA_ARGS__ \ - ) \ -) - -// Chooser - -#define OATPP_MACRO_API_CONTROLLER_ENDPOINT_MACRO_0(METHOD, PATH, NAME) \ -OATPP_MACRO_EXPAND(OATPP_MACRO_API_CONTROLLER_ENDPOINT_0(NAME, METHOD, PATH)) - -#define OATPP_MACRO_API_CONTROLLER_ENDPOINT_MACRO_1(METHOD, PATH, NAME, ...) \ -OATPP_MACRO_EXPAND(OATPP_MACRO_API_CONTROLLER_ENDPOINT_1(NAME, METHOD, PATH, __VA_ARGS__)) - -/** - * Codegen macoro to be used in `oatpp::web::server::api::ApiController` to generate Endpoint. - * @param METHOD - Http method ("GET", "POST", "PUT", etc.). - * @param PATH - Path to endpoint (without host). - * @param NAME - Name of the generated method. - * @return - std::shared_ptr to &id:oatpp::web::protocol::http::outgoing::Response;. - */ -#define ENDPOINT(METHOD, PATH, ...) \ -OATPP_MACRO_EXPAND(OATPP_MACRO_MACRO_BINARY_SELECTOR(OATPP_MACRO_API_CONTROLLER_ENDPOINT_MACRO_, (__VA_ARGS__)) (METHOD, PATH, __VA_ARGS__)) - -// ENDPOINT ASYNC MACRO // ------------------------------------------------------ - -/* - * 1 - Method to obtain endpoint call function ptr - * 2 - Endpoint info singleton - */ -#define OATPP_MACRO_API_CONTROLLER_ENDPOINT_ASYNC_DECL_DEFAULTS(NAME, METHOD, PATH) \ -template<class T> \ -static typename Handler<T>::MethodAsync Z__ENDPOINT_METHOD_##NAME(T* controller) { \ - (void)controller; \ - return &T::Z__PROXY_METHOD_##NAME; \ -} \ -\ -std::shared_ptr<Endpoint::Info> Z__EDNPOINT_INFO_GET_INSTANCE_##NAME() { \ - std::shared_ptr<Endpoint::Info> info = getEndpointInfo(#NAME); \ - if(!info){ \ - info = Endpoint::Info::createShared(); \ - setEndpointInfo(#NAME, info); \ - } \ - return info; \ -} - -/* - * 1 - Endpoint info instance - * 2 - Endpoint instance - */ -#define OATPP_MACRO_API_CONTROLLER_ENDPOINT_ASYNC_DECL(NAME, METHOD, PATH) \ -\ -EndpointInfoBuilder Z__CREATE_ENDPOINT_INFO_##NAME = [this](){ \ - auto info = Z__EDNPOINT_INFO_GET_INSTANCE_##NAME(); \ - info->name = #NAME; \ - info->path = PATH; \ - info->method = METHOD; \ - return info; \ -}; \ -\ -const std::shared_ptr<Endpoint> Z__ENDPOINT_##NAME = createEndpoint(m_endpoints, \ - this, \ - nullptr, \ - Z__ENDPOINT_METHOD_##NAME(this), \ - Z__CREATE_ENDPOINT_INFO_##NAME); - -/** - * Codegen macoro to be used in `oatpp::web::server::api::ApiController` to generate Asynchronous Endpoint. - * @param METHOD - Http method ("GET", "POST", "PUT", etc.). - * @param PATH - Path to endpoint (without host). - * @param NAME - Name of the generated method. - * @return - &id:oatpp::async::Action;. - */ -#define ENDPOINT_ASYNC(METHOD, PATH, NAME) \ -OATPP_MACRO_API_CONTROLLER_ENDPOINT_ASYNC_DECL_DEFAULTS(NAME, METHOD, PATH) \ -OATPP_MACRO_API_CONTROLLER_ENDPOINT_ASYNC_DECL(NAME, METHOD, PATH) \ -\ -oatpp::async::CoroutineStarterForResult<const std::shared_ptr<oatpp::web::protocol::http::outgoing::Response>&> \ -Z__PROXY_METHOD_##NAME(const std::shared_ptr<oatpp::web::protocol::http::incoming::Request>& __request) \ -{ \ - return NAME::startForResult(this, __request); \ -} \ -\ -class NAME : public HandlerCoroutine<NAME, __ControllerType> - -/** - * Auxiliary codegen macro for `ENDPOINT_ASYNC` to generate correct constructor for Asynchronous Endpoint Coroutine. - * @NAME - Name of the endpoint. Exact the same name as was passed to `ENDPOINT_ASYNC` macro. - */ -#define ENDPOINT_ASYNC_INIT(NAME) \ -public: \ -\ - NAME(__ControllerType* pController, \ - const std::shared_ptr<IncomingRequest>& pRequest) \ - : HandlerCoroutine(pController, pRequest) \ - {} +#include "./api_controller/base_define.hpp" +#include "./api_controller/auth_define.hpp" // CORS MACRO // ------------------------------------------------------ diff --git a/src/oatpp/codegen/codegen_undef_ApiController_.hpp b/src/oatpp/codegen/codegen_undef_ApiController_.hpp index 54a0cc20..30dd7de6 100644 --- a/src/oatpp/codegen/codegen_undef_ApiController_.hpp +++ b/src/oatpp/codegen/codegen_undef_ApiController_.hpp @@ -42,133 +42,8 @@ * </ul> */ -#undef OATPP_MACRO_API_CONTROLLER_PARAM_MACRO -#undef OATPP_MACRO_API_CONTROLLER_PARAM_INFO -#undef OATPP_MACRO_API_CONTROLLER_PARAM_TYPE -#undef OATPP_MACRO_API_CONTROLLER_PARAM_NAME -#undef OATPP_MACRO_API_CONTROLLER_PARAM_TYPE_STR -#undef OATPP_MACRO_API_CONTROLLER_PARAM_NAME_STR -#undef OATPP_MACRO_API_CONTROLLER_PARAM - -#undef REQUEST -#undef HEADER -#undef PATH -#undef QUERIES -#undef QUERY -#undef BODY_STRING -#undef BODY_DTO -#undef AUTHORIZATION - -// INIT // ------------------------------------------------------ - -#undef REST_CONTROLLER_INIT - -#undef OATPP_MACRO_API_CONTROLLER_MACRO_SELECTOR - -// REQUEST MACRO // ------------------------------------------------------ - -#undef OATPP_MACRO_API_CONTROLLER_REQUEST -#undef OATPP_MACRO_API_CONTROLLER_REQUEST_INFO - -// HEADER MACRO // ------------------------------------------------------ - -#undef OATPP_MACRO_API_CONTROLLER_HEADER_1 -#undef OATPP_MACRO_API_CONTROLLER_HEADER_2 -#undef OATPP_MACRO_API_CONTROLLER_HEADER - -// __INFO - -#undef OATPP_MACRO_API_CONTROLLER_HEADER_INFO_1 -#undef OATPP_MACRO_API_CONTROLLER_HEADER_INFO_2 -#undef OATPP_MACRO_API_CONTROLLER_HEADER_INFO - -// PATH MACRO // ------------------------------------------------------ - -#undef OATPP_MACRO_API_CONTROLLER_PATH_1 -#undef OATPP_MACRO_API_CONTROLLER_PATH_2 -#undef OATPP_MACRO_API_CONTROLLER_PATH - -// __INFO - -#undef OATPP_MACRO_API_CONTROLLER_PATH_INFO_1 -#undef OATPP_MACRO_API_CONTROLLER_PATH_INFO_2 -#undef OATPP_MACRO_API_CONTROLLER_PATH_INFO - -// QUERIES MACRO // ------------------------------------------------------ - -#undef OATPP_MACRO_API_CONTROLLER_QUERIES -#undef OATPP_MACRO_API_CONTROLLER_QUERIES_INFO - -// QUERY MACRO // ------------------------------------------------------ - -#undef OATPP_MACRO_API_CONTROLLER_QUERY_1 -#undef OATPP_MACRO_API_CONTROLLER_QUERY_2 -#undef OATPP_MACRO_API_CONTROLLER_QUERY - -// __INFO - -#undef OATPP_MACRO_API_CONTROLLER_QUERY_INFO_1 -#undef OATPP_MACRO_API_CONTROLLER_QUERY_INFO_2 -#undef OATPP_MACRO_API_CONTROLLER_QUERY_INFO - -// BODY_STRING MACRO // ------------------------------------------------------ - -#undef OATPP_MACRO_API_CONTROLLER_BODY_STRING - -// __INFO - -#undef OATPP_MACRO_API_CONTROLLER_BODY_STRING_INFO - -// BODY_DTO MACRO // ------------------------------------------------------ - -#undef OATPP_MACRO_API_CONTROLLER_BODY_DTO - -// __INFO - -#undef OATPP_MACRO_API_CONTROLLER_BODY_DTO_INFO - -// AUTHORIZATION MACRO // ------------------------------------------------------ -#undef OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_1 -#undef OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_2 -#undef OATPP_MACRO_API_CONTROLLER_AUTHORIZATION - -// __INFO -#undef OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_INFO_1 -#undef OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_INFO_2 -#undef OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_INFO - -// FOR EACH // ------------------------------------------------------ - -#undef OATPP_MACRO_API_CONTROLLER_FOR_EACH_PARAM_DECL -#undef OATPP_MACRO_API_CONTROLLER_FOR_EACH_PARAM_PUT -#undef OATPP_MACRO_API_CONTROLLER_FOR_EACH_PARAM_CALL -#undef OATPP_MACRO_API_CONTROLLER_FOR_EACH_PARAM_INFO - -// ENDPOINT_INFO MACRO // ------------------------------------------------------ - -#undef ENDPOINT_INFO - -// ENDPOINT MACRO // ------------------------------------------------------ - -#undef OATPP_MACRO_API_CONTROLLER_ENDPOINT_DECL_DEFAULTS - -#undef OATPP_MACRO_API_CONTROLLER_ENDPOINT_DECL_0 -#undef OATPP_MACRO_API_CONTROLLER_ENDPOINT_0 - -#undef OATPP_MACRO_API_CONTROLLER_ENDPOINT_DECL_1 -#undef OATPP_MACRO_API_CONTROLLER_ENDPOINT_1 - -#undef OATPP_MACRO_API_CONTROLLER_ENDPOINT_MACRO_0 -#undef OATPP_MACRO_API_CONTROLLER_ENDPOINT_MACRO_1 - -#undef ENDPOINT - -// ENDPOINT ASYNC MACRO // ------------------------------------------------------ - -#undef OATPP_MACRO_API_CONTROLLER_ENDPOINT_ASYNC_DECL_DEFAULTS -#undef OATPP_MACRO_API_CONTROLLER_ENDPOINT_ASYNC_DECL -#undef ENDPOINT_ASYNC -#undef ENDPOINT_ASYNC_INIT +#include "./api_controller/base_undef.hpp" +#include "./api_controller/auth_undef.hpp" // CORS MACRO // ------------------------------------------------------ diff --git a/src/oatpp/network/client/SimpleTCPConnectionProvider.cpp b/src/oatpp/network/client/SimpleTCPConnectionProvider.cpp index 8d89c356..21edba29 100644 --- a/src/oatpp/network/client/SimpleTCPConnectionProvider.cpp +++ b/src/oatpp/network/client/SimpleTCPConnectionProvider.cpp @@ -126,12 +126,14 @@ oatpp::async::CoroutineStarterForResult<const std::shared_ptr<oatpp::data::strea private: struct addrinfo* m_result; struct addrinfo* m_currentResult; + bool m_isHandleOpened; public: ConnectCoroutine(const oatpp::String& host, v_int32 port) : m_host(host) , m_port(port) , m_result(nullptr) + , m_isHandleOpened(false) {} ~ConnectCoroutine() { @@ -141,7 +143,6 @@ oatpp::async::CoroutineStarterForResult<const std::shared_ptr<oatpp::data::strea } Action act() override { - auto portStr = oatpp::utils::conversion::int32ToStr(m_port); struct addrinfo hints; @@ -170,24 +171,41 @@ oatpp::async::CoroutineStarterForResult<const std::shared_ptr<oatpp::data::strea } - Action iterateAddrInfoResults() { + /* + * Close previously opened socket here. + * Don't ever close socket in the method which returns action ioWait or ioRepeat + */ + if(m_isHandleOpened) { + m_isHandleOpened = false; +#if defined(WIN32) || defined(_WIN32) + ::closesocket(m_clientHandle); +#else + ::close(m_clientHandle); +#endif + + } + if(m_currentResult != nullptr) { m_clientHandle = socket(m_currentResult->ai_family, m_currentResult->ai_socktype, m_currentResult->ai_protocol); - if (m_clientHandle < 0) { // TODO - For windows it should check for SOCKET_ERROR constant +#if defined(WIN32) || defined(_WIN32) + if (m_clientHandle == INVALID_SOCKET) { m_currentResult = m_currentResult->ai_next; return repeat(); } - -#if defined(WIN32) || defined(_WIN32) u_long flags = 1; ioctlsocket(m_clientHandle, FIONBIO, &flags); #else + if (m_clientHandle < 0) { + m_currentResult = m_currentResult->ai_next; + return repeat(); + } fcntl(m_clientHandle, F_SETFL, O_NONBLOCK); #endif + #ifdef SO_NOSIGPIPE int yes = 1; v_int32 ret = setsockopt(m_clientHandle, SOL_SOCKET, SO_NOSIGPIPE, &yes, sizeof(int)); @@ -195,7 +213,10 @@ oatpp::async::CoroutineStarterForResult<const std::shared_ptr<oatpp::data::strea OATPP_LOGD("[oatpp::network::client::SimpleTCPConnectionProvider::getConnectionAsync()]", "Warning. Failed to set %s for socket", "SO_NOSIGPIPE"); } #endif + + m_isHandleOpened = true; return yieldTo(&ConnectCoroutine::doConnect); + } return error<Error>("[oatpp::network::client::SimpleTCPConnectionProvider::getConnectionAsync()]: Error. Can't connect."); @@ -203,7 +224,6 @@ oatpp::async::CoroutineStarterForResult<const std::shared_ptr<oatpp::data::strea } Action doConnect() { - errno = 0; auto res = connect(m_clientHandle, m_currentResult->ai_addr, m_currentResult->ai_addrlen); @@ -221,8 +241,6 @@ oatpp::async::CoroutineStarterForResult<const std::shared_ptr<oatpp::data::strea return ioRepeat(m_clientHandle, oatpp::async::Action::IOEventType::IO_EVENT_WRITE); } - ::closesocket(m_clientHandle); - #else if(res == 0 || errno == EISCONN) { @@ -234,8 +252,6 @@ oatpp::async::CoroutineStarterForResult<const std::shared_ptr<oatpp::data::strea return ioRepeat(m_clientHandle, oatpp::async::Action::IOEventType::IO_EVENT_WRITE); } - ::close(m_clientHandle); - #endif m_currentResult = m_currentResult->ai_next; diff --git a/src/oatpp/web/protocol/http/incoming/Request.cpp b/src/oatpp/web/protocol/http/incoming/Request.cpp index 21b8fb9d..be94e273 100644 --- a/src/oatpp/web/protocol/http/incoming/Request.cpp +++ b/src/oatpp/web/protocol/http/incoming/Request.cpp @@ -89,6 +89,19 @@ std::shared_ptr<const http::incoming::BodyDecoder> Request::getBodyDecoder() con return m_bodyDecoder; } +void Request::putHeader(const oatpp::data::share::StringKeyLabelCI_FAST& key, const oatpp::data::share::StringKeyLabel& value) { + m_headers[key] = value; +} + +bool Request::putHeaderIfNotExists(const oatpp::data::share::StringKeyLabelCI_FAST& key, const oatpp::data::share::StringKeyLabel& value) { + auto it = m_headers.find(key); + if(it == m_headers.end()) { + m_headers.insert({key, value}); + return true; + } + return false; +} + oatpp::String Request::getHeader(const oatpp::data::share::StringKeyLabelCI_FAST& headerName) const{ auto it = m_headers.find(headerName); if(it != m_headers.end()) { diff --git a/src/oatpp/web/protocol/http/incoming/Request.hpp b/src/oatpp/web/protocol/http/incoming/Request.hpp index 0091fc14..3d0c3bae 100644 --- a/src/oatpp/web/protocol/http/incoming/Request.hpp +++ b/src/oatpp/web/protocol/http/incoming/Request.hpp @@ -126,10 +126,25 @@ public: */ std::shared_ptr<const http::incoming::BodyDecoder> getBodyDecoder() const; + /** + * Add http header. + * @param key - &id:oatpp::data::share::StringKeyLabelCI_FAST;. + * @param value - &id:oatpp::data::share::StringKeyLabel;. + */ + void putHeader(const oatpp::data::share::StringKeyLabelCI_FAST& key, const oatpp::data::share::StringKeyLabel& value); + + /** + * Add http header if not already exists. + * @param key - &id:oatpp::data::share::StringKeyLabelCI_FAST;. + * @param value - &id:oatpp::data::share::StringKeyLabel;. + * @return - `true` if header was added. + */ + bool putHeaderIfNotExists(const oatpp::data::share::StringKeyLabelCI_FAST& key, const oatpp::data::share::StringKeyLabel& value); + /** * Get header value - * @param headerName - * @return header value + * @param headerName - &id:oatpp::data::share::StringKeyLabelCI_FAST;. + * @return - &id:oatpp::String;. */ oatpp::String getHeader(const oatpp::data::share::StringKeyLabelCI_FAST& headerName) const; diff --git a/src/oatpp/web/protocol/http/outgoing/Response.cpp b/src/oatpp/web/protocol/http/outgoing/Response.cpp index 9b21e24e..a9ebcbad 100644 --- a/src/oatpp/web/protocol/http/outgoing/Response.cpp +++ b/src/oatpp/web/protocol/http/outgoing/Response.cpp @@ -60,6 +60,14 @@ bool Response::putHeaderIfNotExists(const oatpp::data::share::StringKeyLabelCI_F return false; } +oatpp::String Response::getHeader(const oatpp::data::share::StringKeyLabelCI_FAST& headerName) const { + auto it = m_headers.find(headerName); + if(it != m_headers.end()) { + return it->second.toString(); + } + return nullptr; +} + void Response::setConnectionUpgradeHandler(const std::shared_ptr<oatpp::network::server::ConnectionHandler>& handler) { m_connectionUpgradeHandler = handler; } diff --git a/src/oatpp/web/protocol/http/outgoing/Response.hpp b/src/oatpp/web/protocol/http/outgoing/Response.hpp index 981694e9..e4099fc3 100644 --- a/src/oatpp/web/protocol/http/outgoing/Response.hpp +++ b/src/oatpp/web/protocol/http/outgoing/Response.hpp @@ -100,6 +100,13 @@ public: */ bool putHeaderIfNotExists(const oatpp::data::share::StringKeyLabelCI_FAST& key, const oatpp::data::share::StringKeyLabel& value); + /** + * Get header value + * @param headerName - &id:oatpp::data::share::StringKeyLabelCI_FAST;. + * @return - &id:oatpp::String;. + */ + oatpp::String getHeader(const oatpp::data::share::StringKeyLabelCI_FAST& headerName) const; + /** * Set connection upgreade header. <br> * Use it together with corresponding headers being set when Response is created as: <br> diff --git a/src/oatpp/web/server/api/ApiController.cpp b/src/oatpp/web/server/api/ApiController.cpp index 4256805d..d03c94a7 100644 --- a/src/oatpp/web/server/api/ApiController.cpp +++ b/src/oatpp/web/server/api/ApiController.cpp @@ -48,6 +48,14 @@ std::shared_ptr<ApiController::Endpoint::Info> ApiController::getEndpointInfo(co return m_endpointInfo[endpointName]; } +void ApiController::setEndpointHandler(const std::string& endpointName, const std::shared_ptr<RequestHandler>& handler) { + m_endpointHandlers[endpointName] = handler; +} + +std::shared_ptr<ApiController::RequestHandler> ApiController::getEndpointHandler(const std::string& endpointName) { + return m_endpointHandlers[endpointName]; +} + void ApiController::setErrorHandler(const std::shared_ptr<handler::ErrorHandler>& errorHandler){ m_errorHandler = errorHandler; } diff --git a/src/oatpp/web/server/api/ApiController.hpp b/src/oatpp/web/server/api/ApiController.hpp index 35288318..91469b30 100644 --- a/src/oatpp/web/server/api/ApiController.hpp +++ b/src/oatpp/web/server/api/ApiController.hpp @@ -105,6 +105,11 @@ public: */ typedef oatpp::collection::LinkedList<std::shared_ptr<Endpoint>> Endpoints; + /** + * Convenience typedef for &id:oatpp::web::server::HttpRequestHandler;. + */ + typedef oatpp::web::server::HttpRequestHandler RequestHandler; + /** * Convenience typedef for &id:oatpp::web::server::handler::AuthorizationHandler;. */ @@ -185,7 +190,7 @@ protected: * Handler which subscribes to specific URL in Router and delegates calls endpoints */ template<class T> - class Handler : public oatpp::web::server::HttpRequestHandler { + class Handler : public RequestHandler { public: typedef std::shared_ptr<OutgoingResponse> (T::*Method)(const std::shared_ptr<protocol::http::incoming::Request>&); typedef oatpp::async::CoroutineStarterForResult<const std::shared_ptr<OutgoingResponse>&> @@ -221,8 +226,55 @@ protected: } throw oatpp::web::protocol::http::HttpError(Status::CODE_500, "Using Async model for non async endpoint"); } + + Method setMethod(Method method) { + auto prev = m_method; + m_method = method; + return prev; + } + + Method getMethod() { + return m_method; + } + + MethodAsync setMethodAsync(MethodAsync methodAsync) { + auto prev = m_methodAsync; + m_methodAsync = methodAsync; + return prev; + } + + MethodAsync getMethodAsync() { + return m_methodAsync; + } }; + +protected: + + /* + * Set endpoint info by endpoint name. (Endpoint name is the 'NAME' parameter of the ENDPOINT macro) + * Info should be set before call to addEndpointsToRouter(); + */ + void setEndpointInfo(const std::string& endpointName, const std::shared_ptr<Endpoint::Info>& info); + + /* + * Get endpoint info by endpoint name. (Endpoint name is the 'NAME' parameter of the ENDPOINT macro) + */ + std::shared_ptr<Endpoint::Info> getEndpointInfo(const std::string& endpointName); + + /* + * Set endpoint Request handler. + * @param endpointName + * @param handler + */ + void setEndpointHandler(const std::string& endpointName, const std::shared_ptr<RequestHandler>& handler); + + /* + * Get endpoint Request handler. + * @param endpointName + * @return + */ + std::shared_ptr<RequestHandler> getEndpointHandler(const std::string& endpointName); protected: std::shared_ptr<Endpoints> m_endpoints; @@ -231,6 +283,7 @@ protected: std::shared_ptr<handler::AuthorizationHandler> m_defaultAuthorizationHandler; std::shared_ptr<oatpp::data::mapping::ObjectMapper> m_defaultObjectMapper; std::unordered_map<std::string, std::shared_ptr<Endpoint::Info>> m_endpointInfo; + std::unordered_map<std::string, std::shared_ptr<RequestHandler>> m_endpointHandlers; public: ApiController(const std::shared_ptr<oatpp::data::mapping::ObjectMapper>& defaultObjectMapper) : m_endpoints(Endpoints::createShared()) @@ -242,11 +295,9 @@ public: template<class T> static std::shared_ptr<Endpoint> createEndpoint(const std::shared_ptr<Endpoints>& endpoints, - T* controller, - typename Handler<T>::Method method, - typename Handler<T>::MethodAsync methodAsync, - const EndpointInfoBuilder& infoBuilder){ - auto handler = Handler<T>::createShared(controller, method, methodAsync); + const std::shared_ptr<Handler<T>>& handler, + const EndpointInfoBuilder& infoBuilder) + { auto endpoint = Endpoint::createShared(handler, infoBuilder); endpoints->pushBack(endpoint); return endpoint; @@ -272,17 +323,6 @@ public: * Get list of Endpoints created via ENDPOINT macro */ std::shared_ptr<Endpoints> getEndpoints(); - - /** - * Set endpoint info by endpoint name. (Endpoint name is the 'NAME' parameter of the ENDPOINT macro) - * Info should be set before call to addEndpointsToRouter(); - */ - void setEndpointInfo(const std::string& endpointName, const std::shared_ptr<Endpoint::Info>& info); - - /** - * Get endpoint info by endpoint name. (Endpoint name is the 'NAME' parameter of the ENDPOINT macro) - */ - std::shared_ptr<Endpoint::Info> getEndpointInfo(const std::string& endpointName); /** * [under discussion] diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index a1e473c5..2e7c28c7 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -51,14 +51,16 @@ add_executable(oatppAllTests oatpp/web/FullAsyncTest.hpp oatpp/web/FullTest.cpp oatpp/web/FullTest.hpp + oatpp/web/FullAsyncClientTest.cpp + oatpp/web/FullAsyncClientTest.hpp oatpp/web/app/Client.hpp oatpp/web/app/BearerAuthorizationController.hpp oatpp/web/app/BasicAuthorizationController.hpp oatpp/web/app/Controller.hpp oatpp/web/app/ControllerAsync.hpp oatpp/web/app/DTOs.hpp - oatpp/web/FullAsyncClientTest.cpp - oatpp/web/FullAsyncClientTest.hpp + oatpp/web/app/ControllerWithInterceptors.hpp + oatpp/web/app/ControllerWithInterceptorsAsync.hpp ) target_link_libraries(oatppAllTests PRIVATE oatpp PRIVATE oatpp-test) diff --git a/test/oatpp/web/FullAsyncClientTest.cpp b/test/oatpp/web/FullAsyncClientTest.cpp index 05b8d9b7..b8e9efb0 100644 --- a/test/oatpp/web/FullAsyncClientTest.cpp +++ b/test/oatpp/web/FullAsyncClientTest.cpp @@ -154,6 +154,7 @@ public: } else { OATPP_LOGE("[FullAsyncClientTest::ClientCoroutine_getRootAsync::handleError()]", "Error. %s", error->what()); } + OATPP_ASSERT(!"Error"); return error; } @@ -195,6 +196,7 @@ public: } else { OATPP_LOGE("[FullAsyncClientTest::ClientCoroutine_postBodyAsync::handleError()]", "Error. %s", error->what()); } + OATPP_ASSERT(!"Error"); return error; } @@ -242,6 +244,7 @@ public: OATPP_LOGE("[FullAsyncClientTest::ClientCoroutine_echoBodyAsync::handleError()]", "Error. %s", error->what()); } } + OATPP_ASSERT(!"Error"); return error; } diff --git a/test/oatpp/web/FullAsyncTest.cpp b/test/oatpp/web/FullAsyncTest.cpp index 743daef0..d2f53bf4 100644 --- a/test/oatpp/web/FullAsyncTest.cpp +++ b/test/oatpp/web/FullAsyncTest.cpp @@ -26,6 +26,7 @@ #include "oatpp/web/app/Client.hpp" +#include "oatpp/web/app/ControllerWithInterceptorsAsync.hpp" #include "oatpp/web/app/ControllerAsync.hpp" #include "oatpp/web/client/HttpRequestExecutor.hpp" @@ -143,6 +144,7 @@ void FullAsyncTest::onRun() { oatpp::test::web::ClientServerTestRunner runner; runner.addController(app::ControllerAsync::createShared()); + runner.addController(app::ControllerWithInterceptorsAsync::createShared()); runner.run([this, &runner] { @@ -256,6 +258,13 @@ void FullAsyncTest::onRun() { } + { // test interceptor GET + auto response = client->getInterceptors(connection); + OATPP_ASSERT(response->getStatusCode() == 200); + auto value = response->readBodyToString(); + OATPP_ASSERT(value == "Hello World Async!!!"); + } + if((i + 1) % iterationsStep == 0) { auto ticks = oatpp::base::Environment::getMicroTickCount() - lastTick; lastTick = oatpp::base::Environment::getMicroTickCount(); diff --git a/test/oatpp/web/FullTest.cpp b/test/oatpp/web/FullTest.cpp index 2b2c8355..2d746b8d 100644 --- a/test/oatpp/web/FullTest.cpp +++ b/test/oatpp/web/FullTest.cpp @@ -26,6 +26,7 @@ #include "oatpp/web/app/Client.hpp" +#include "oatpp/web/app/ControllerWithInterceptors.hpp" #include "oatpp/web/app/Controller.hpp" #include "oatpp/web/app/BasicAuthorizationController.hpp" #include "oatpp/web/app/BearerAuthorizationController.hpp" @@ -140,6 +141,7 @@ void FullTest::onRun() { oatpp::test::web::ClientServerTestRunner runner; runner.addController(app::Controller::createShared()); + runner.addController(app::ControllerWithInterceptors::createShared()); runner.addController(app::DefaultBasicAuthorizationController::createShared()); runner.addController(app::BasicAuthorizationController::createShared()); runner.addController(app::BearerAuthorizationController::createShared()); @@ -431,6 +433,13 @@ void FullTest::onRun() { } + { // test interceptors + auto response = client->getInterceptors(connection); + OATPP_ASSERT(response->getStatusCode() == 200); + auto value = response->readBodyToString(); + OATPP_ASSERT(value == "Hello World!!!"); + } + if((i + 1) % iterationsStep == 0) { auto ticks = oatpp::base::Environment::getMicroTickCount() - lastTick; lastTick = oatpp::base::Environment::getMicroTickCount(); diff --git a/test/oatpp/web/app/Client.hpp b/test/oatpp/web/app/Client.hpp index 04772f00..2f3587da 100644 --- a/test/oatpp/web/app/Client.hpp +++ b/test/oatpp/web/app/Client.hpp @@ -65,6 +65,8 @@ public: API_CALL("GET", "chunked/{text-value}/{num-iterations}", getChunked, PATH(String, text, "text-value"), PATH(Int32, numIterations, "num-iterations")) API_CALL("POST", "test/multipart/{chunk-size}", multipartTest, PATH(Int32, chunkSize, "chunk-size"), BODY(std::shared_ptr<MultipartBody>, body)) + API_CALL("GET", "test/interceptors", getInterceptors) + API_CALL_ASYNC("GET", "/", getRootAsync) API_CALL_ASYNC("GET", "/", getRootAsyncWithCKA, HEADER(String, connection, "Connection")) API_CALL_ASYNC("GET", "params/{param}", getWithParamsAsync, PATH(String, param)) diff --git a/test/oatpp/web/app/Controller.hpp b/test/oatpp/web/app/Controller.hpp index 082d4cda..6512da36 100644 --- a/test/oatpp/web/app/Controller.hpp +++ b/test/oatpp/web/app/Controller.hpp @@ -61,8 +61,16 @@ public: #include OATPP_CODEGEN_BEGIN(ApiController) + /*ENDPOINT_INTERCEPTOR(root, inter1) { + OATPP_LOGD("aaa", "inter1"); + return (this->*prevMethod)(request); + }*/ + /*ENDPOINT_INTERCEPTOR(root, inter2) { + OATPP_LOGD("aaa", "inter2"); + return (this->*prevMethod)(request); + }*/ ENDPOINT("GET", "/", root) { -// OATPP_LOGV(TAG, "GET '/'"); + //OATPP_LOGV(TAG, "GET '/'"); return createResponse(Status::CODE_200, "Hello World!!!"); } diff --git a/test/oatpp/web/app/ControllerAsync.hpp b/test/oatpp/web/app/ControllerAsync.hpp index 6e843040..9e1d3dbc 100644 --- a/test/oatpp/web/app/ControllerAsync.hpp +++ b/test/oatpp/web/app/ControllerAsync.hpp @@ -60,7 +60,16 @@ public: } #include OATPP_CODEGEN_BEGIN(ApiController) - + +// ENDPOINT_INTERCEPTOR_ASYNC(Root, inter1) { +// OATPP_LOGD("aaa", "inter1"); +// return (this->*prevMethod)(request); +// } +// ENDPOINT_INTERCEPTOR(root, inter2) { +// OATPP_LOGD("aaa", "inter2"); +// return (this->*prevMethod)(request); +// } + ENDPOINT_ASYNC("GET", "/", Root) { ENDPOINT_ASYNC_INIT(Root) diff --git a/test/oatpp/web/app/ControllerWithInterceptors.hpp b/test/oatpp/web/app/ControllerWithInterceptors.hpp new file mode 100644 index 00000000..4b7036c1 --- /dev/null +++ b/test/oatpp/web/app/ControllerWithInterceptors.hpp @@ -0,0 +1,114 @@ +/*************************************************************************** + * + * Project _____ __ ____ _ _ + * ( _ ) /__\ (_ _)_| |_ _| |_ + * )(_)( /(__)\ )( (_ _)(_ _) + * (_____)(__)(__)(__) |_| |_| + * + * + * Copyright 2018-present, Leonid Stryzhevskyi <lganzzzo@gmail.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************/ + +#ifndef oatpp_test_web_app_ControllerWithInterceptors_hpp +#define oatpp_test_web_app_ControllerWithInterceptors_hpp + +#include "oatpp/web/server/api/ApiController.hpp" +#include "oatpp/parser/json/mapping/ObjectMapper.hpp" +#include "oatpp/core/utils/ConversionUtils.hpp" +#include "oatpp/core/macro/codegen.hpp" +#include "oatpp/core/macro/component.hpp" + +#include <sstream> + +namespace oatpp { namespace test { namespace web { namespace app { + +namespace multipart = oatpp::web::mime::multipart; + +class ControllerWithInterceptors : public oatpp::web::server::api::ApiController { +private: + static constexpr const char* TAG = "test::web::app::ControllerWithInterceptors"; +public: + ControllerWithInterceptors(const std::shared_ptr<ObjectMapper>& objectMapper) + : oatpp::web::server::api::ApiController(objectMapper) + {} +public: + + static std::shared_ptr<ControllerWithInterceptors> createShared(const std::shared_ptr<ObjectMapper>& objectMapper = OATPP_GET_COMPONENT(std::shared_ptr<ObjectMapper>)){ + return std::make_shared<ControllerWithInterceptors>(objectMapper); + } + +#include OATPP_CODEGEN_BEGIN(ApiController) + + ENDPOINT_INTERCEPTOR(interceptor, inter1) { + + /* assert order of interception */ + OATPP_ASSERT(request->getHeader("header-in-inter2") == "inter2"); + OATPP_ASSERT(request->getHeader("header-in-inter3") == "inter3"); + /********************************/ + + request->putHeader("header-in-inter1", "inter1"); + auto response = (this->*intercepted)(request); + response->putHeader("header-out-inter1", "inter1"); + return response; + + } + ENDPOINT_INTERCEPTOR(interceptor, inter2) { + + /* assert order of interception */ + OATPP_ASSERT(request->getHeader("header-in-inter3") == "inter3"); + /********************************/ + + request->putHeader("header-in-inter2", "inter2"); + auto response = (this->*intercepted)(request); + response->putHeader("header-out-inter2", "inter2"); + return response; + + } + ENDPOINT_INTERCEPTOR(interceptor, inter3) { + request->putHeader("header-in-inter3", "inter3"); + auto response = (this->*intercepted)(request); + response->putHeader("header-out-inter3", "inter3"); + return response; + } + ENDPOINT_INTERCEPTOR(interceptor, asserter) { + auto response = (this->*intercepted)(request); + + OATPP_ASSERT(response->getHeader("header-out-inter1") == "inter1"); + OATPP_ASSERT(response->getHeader("header-out-inter2") == "inter2"); + OATPP_ASSERT(response->getHeader("header-out-inter3") == "inter3"); + + return response; + } + ENDPOINT("GET", "test/interceptors", interceptor, + REQUEST(std::shared_ptr<IncomingRequest>, request)) + { + + OATPP_ASSERT(request->getHeader("header-in-inter1") == "inter1"); + OATPP_ASSERT(request->getHeader("header-in-inter2") == "inter2"); + OATPP_ASSERT(request->getHeader("header-in-inter3") == "inter3"); + + return createResponse(Status::CODE_200, "Hello World!!!"); + + } + + +#include OATPP_CODEGEN_END(ApiController) + +}; + +}}}} + +#endif /* oatpp_test_web_app_ControllerWithInterceptors_hpp */ diff --git a/test/oatpp/web/app/ControllerWithInterceptorsAsync.hpp b/test/oatpp/web/app/ControllerWithInterceptorsAsync.hpp new file mode 100644 index 00000000..f2c1825f --- /dev/null +++ b/test/oatpp/web/app/ControllerWithInterceptorsAsync.hpp @@ -0,0 +1,160 @@ +/*************************************************************************** + * + * Project _____ __ ____ _ _ + * ( _ ) /__\ (_ _)_| |_ _| |_ + * )(_)( /(__)\ )( (_ _)(_ _) + * (_____)(__)(__)(__) |_| |_| + * + * + * Copyright 2018-present, Leonid Stryzhevskyi <lganzzzo@gmail.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************/ + +#ifndef oatpp_test_web_app_ControllerWithInterceptorsAsync_hpp +#define oatpp_test_web_app_ControllerWithInterceptorsAsync_hpp + +#include "oatpp/web/server/api/ApiController.hpp" +#include "oatpp/parser/json/mapping/ObjectMapper.hpp" +#include "oatpp/core/utils/ConversionUtils.hpp" +#include "oatpp/core/macro/codegen.hpp" +#include "oatpp/core/macro/component.hpp" + +#include <sstream> + +namespace oatpp { namespace test { namespace web { namespace app { + +namespace multipart = oatpp::web::mime::multipart; + +class ControllerWithInterceptorsAsync : public oatpp::web::server::api::ApiController { +private: + static constexpr const char* TAG = "test::web::app::ControllerWithInterceptorsAsync"; +public: + ControllerWithInterceptorsAsync(const std::shared_ptr<ObjectMapper>& objectMapper) + : oatpp::web::server::api::ApiController(objectMapper) + {} +public: + + static std::shared_ptr<ControllerWithInterceptorsAsync> createShared(const std::shared_ptr<ObjectMapper>& objectMapper = OATPP_GET_COMPONENT(std::shared_ptr<ObjectMapper>)){ + return std::make_shared<ControllerWithInterceptorsAsync>(objectMapper); + } + +#include OATPP_CODEGEN_BEGIN(ApiController) + + ENDPOINT_INTERCEPTOR_ASYNC(Interceptor, inter1) { + + /* assert order of interception */ + OATPP_ASSERT(request->getHeader("header-in-inter2") == "inter2"); + OATPP_ASSERT(request->getHeader("header-in-inter3") == "inter3"); + /********************************/ + + request->putHeader("header-in-inter1", "inter1"); + return (this->*intercepted)(request); + + } + ENDPOINT_INTERCEPTOR_ASYNC(Interceptor, inter2) { + + /* assert order of interception */ + OATPP_ASSERT(request->getHeader("header-in-inter3") == "inter3"); + /********************************/ + + request->putHeader("header-in-inter2", "inter2"); + return (this->*intercepted)(request); + + } + ENDPOINT_INTERCEPTOR_ASYNC(Interceptor, inter3) { + + class IterceptorCoroutine : public oatpp::async::CoroutineWithResult<IterceptorCoroutine, const std::shared_ptr<OutgoingResponse>&> { + private: + ControllerWithInterceptorsAsync* m_this; + Handler<ControllerWithInterceptorsAsync>::MethodAsync m_intercepted; + std::shared_ptr<IncomingRequest> m_request; + public: + + IterceptorCoroutine(ControllerWithInterceptorsAsync* _this, + const Handler<ControllerWithInterceptorsAsync>::MethodAsync& intercepted, + const std::shared_ptr<IncomingRequest>& request) + : m_this(_this) + , m_intercepted(intercepted) + , m_request(request) + {} + + oatpp::async::Action act() override { + m_request->putHeader("header-in-inter3", "inter3"); + return (m_this->*m_intercepted)(m_request).callbackTo(&IterceptorCoroutine::onResponse); + } + + oatpp::async::Action onResponse(const std::shared_ptr<OutgoingResponse>& response) { + response->putHeader("header-out-inter3", "inter3"); + return this->_return(response); + } + + }; + + return IterceptorCoroutine::startForResult(this, intercepted, request); + + } + ENDPOINT_INTERCEPTOR_ASYNC(Interceptor, asserter) { + + class IterceptorCoroutine : public oatpp::async::CoroutineWithResult<IterceptorCoroutine, const std::shared_ptr<OutgoingResponse>&> { + private: + ControllerWithInterceptorsAsync* m_this; + Handler<ControllerWithInterceptorsAsync>::MethodAsync m_intercepted; + std::shared_ptr<IncomingRequest> m_request; + public: + + IterceptorCoroutine(ControllerWithInterceptorsAsync* _this, + const Handler<ControllerWithInterceptorsAsync>::MethodAsync& intercepted, + const std::shared_ptr<IncomingRequest>& request) + : m_this(_this) + , m_intercepted(intercepted) + , m_request(request) + {} + + oatpp::async::Action act() override { + return (m_this->*m_intercepted)(m_request).callbackTo(&IterceptorCoroutine::onResponse); + } + + oatpp::async::Action onResponse(const std::shared_ptr<OutgoingResponse>& response) { + OATPP_ASSERT(response->getHeader("header-out-inter3") == "inter3"); + return this->_return(response); + } + + }; + + return IterceptorCoroutine::startForResult(this, intercepted, request); + + } + ENDPOINT_ASYNC("GET", "test/interceptors", Interceptor) { + + ENDPOINT_ASYNC_INIT(Interceptor) + + Action act() { + + OATPP_ASSERT(request->getHeader("header-in-inter1") == "inter1"); + OATPP_ASSERT(request->getHeader("header-in-inter2") == "inter2"); + OATPP_ASSERT(request->getHeader("header-in-inter3") == "inter3"); + + return _return(controller->createResponse(Status::CODE_200, "Hello World Async!!!")); + } + + }; + +#include OATPP_CODEGEN_END(ApiController) + +}; + +}}}} + +#endif /* oatpp_test_web_app_ControllerWithInterceptorsAsync_hpp */