ApiController. Better Controller level ErrorHandling for Async API.

This commit is contained in:
lganzzzo 2019-12-20 09:55:10 +02:00
parent 5cabf8ed0e
commit b19f9bb361
2 changed files with 45 additions and 5 deletions

View File

@ -109,5 +109,5 @@ std::shared_ptr<ApiController::OutgoingResponse> ApiController::createDtoRespons
const oatpp::data::mapping::type::AbstractObjectWrapper& dto) const {
return ResponseFactory::createResponse(status, dto, m_defaultObjectMapper.get());
}
}}}}

View File

@ -190,6 +190,36 @@ protected:
typedef std::shared_ptr<OutgoingResponse> (T::*Method)(const std::shared_ptr<IncomingRequest>&);
typedef oatpp::async::CoroutineStarterForResult<const std::shared_ptr<OutgoingResponse>&>
(T::*MethodAsync)(const std::shared_ptr<IncomingRequest>&);
private:
class ErrorHandlingCoroutine : public oatpp::async::CoroutineWithResult<ErrorHandlingCoroutine, const std::shared_ptr<OutgoingResponse>&> {
private:
Handler* m_handler;
std::shared_ptr<IncomingRequest> m_request;
public:
ErrorHandlingCoroutine(Handler* handler, const std::shared_ptr<IncomingRequest>& request)
: m_handler(handler)
, m_request(request)
{}
async::Action act() override {
return (m_handler->m_controller->*m_handler->m_methodAsync)(m_request)
.callbackTo(&ErrorHandlingCoroutine::onResponse);
}
async::Action onResponse(const std::shared_ptr<OutgoingResponse>& response) {
return this->_return(response);
}
async::Action handleError(async::Error* error) override {
auto response = m_handler->m_controller->m_errorHandler->handleError(protocol::http::Status::CODE_500, error->what());
return this->_return(response);
}
};
private:
T* m_controller;
Method m_method;
@ -209,7 +239,10 @@ protected:
std::shared_ptr<OutgoingResponse> handle(const std::shared_ptr<IncomingRequest>& request) override {
if(m_method == nullptr) {
return m_controller->handleError(Status::CODE_500, "Using simple model for Async endpoint");
if(m_methodAsync == nullptr) {
return m_controller->handleError(Status::CODE_500, "[ApiController]: Error. Handler method is nullptr.");
}
return m_controller->handleError(Status::CODE_500, "[ApiController]: Error. Non-async call to async endpoint.");
}
if(m_controller->m_errorHandler) {
@ -224,17 +257,24 @@ protected:
return m_controller->m_errorHandler->handleError(protocol::http::Status::CODE_500, "Unknown error");
}
} else {
return (m_controller->*m_method)(request);
}
return (m_controller->*m_method)(request);
}
oatpp::async::CoroutineStarterForResult<const std::shared_ptr<OutgoingResponse>&>
handleAsync(const std::shared_ptr<protocol::http::incoming::Request>& request) override {
if(m_methodAsync == nullptr) {
throw oatpp::web::protocol::http::HttpError(Status::CODE_500, "Using Async model for non async endpoint");
if(m_method == nullptr) {
throw oatpp::web::protocol::http::HttpError(Status::CODE_500, "[ApiController]: Error. Handler method is nullptr.");
}
throw oatpp::web::protocol::http::HttpError(Status::CODE_500, "[ApiController]: Error. Async call to non-async endpoint.");
}
if(m_controller->m_errorHandler) {
return ErrorHandlingCoroutine::startForResult(this, request);
}
return (m_controller->*m_methodAsync)(request);