From 9ba892ec50acf724d0e0f1125aefe5b248e0759b Mon Sep 17 00:00:00 2001 From: Leonid Stryzhevskyi Date: Tue, 4 Jun 2024 03:36:17 +0300 Subject: [PATCH] changelog/1.4.0: add 'Better error handling' section. --- changelog/1.4.0.md | 61 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/changelog/1.4.0.md b/changelog/1.4.0.md index 3928a71a..1602fa45 100644 --- a/changelog/1.4.0.md +++ b/changelog/1.4.0.md @@ -13,6 +13,7 @@ Contents: - [Remapper](#remapper) - [oatpp::web::mime::ContentMappers](#oatppwebmimecontentmappers) - [New OATPP_LOGx format](#new-oatpp_logx-format) +- [Better error handling](#better-error-handling) - [Restructuring](#restructuring) @@ -172,6 +173,66 @@ Instead of old formatting "%s", "%d", "%f" use "{}" for any variable type: OATPP_LOGd("MyController", "User: name={}, age={}", user->name, user->age) ``` +## Better error handling + +Fixed error handling in the `ApiController` and `ConnectionHandler`. + +The new recommended way to implement custom error handler: + +```cpp +/** + * Extend the DefaultErrorHandling class by overriding the renderError() method instead of the handleError() method. + * You can still override the handleError() method, but in most cases, it isn't necessary. + */ +class ErrorHandler : public oatpp::web::server::handler::DefaultErrorHandler { +private: + /* mappers to map response according to 'Accept' header and available mappers */ + std::shared_ptr m_mappers; +public: + + ErrorHandler(const std::shared_ptr& mappers) + : m_mappers(mappers) + {} + + std::shared_ptr renderError(const HttpServerErrorStacktrace& stacktrace) override { + + /* create ErrorDto */ + auto error = ErrorDto::createShared(); + error->code = stacktrace.status.code; + error->stack = {}; // initialize stack as empty list + + /* push all items of stacktrace */ + for(auto& s : stacktrace.stack) { + error->stack->push_back(s); + } + + /* get all variants of acceptable mime-types from request */ + std::vector acceptable; + if(stacktrace.request) { + acceptable = stacktrace.request->getHeaderValues("Accept"); + } + + /* select mapper based on provided preferences */ + auto mapper = m_mappers->selectMapper(acceptable); + if(!mapper) { + mapper = m_mappers->getDefaultMapper(); + } + + /* create response object */ + auto response = ResponseFactory::createResponse(stacktrace.status, error, mapper); + + /* put all error related headers */ + for(const auto& pair : stacktrace.headers.getAll()) { + response->putHeader(pair.first.toString(), pair.second.toString()); + } + + /* return response */ + return response; + + } + +}; +``` ## Restructuring