From 83774093914b134360d7587609002f19e96a468e Mon Sep 17 00:00:00 2001 From: Leonid Stryzhevskyi Date: Wed, 15 May 2024 18:19:12 +0300 Subject: [PATCH] ContentMappers: proper handling of Content-Type header --- .../codegen/api_controller/base_define.hpp | 4 ++-- src/oatpp/web/mime/ContentMappers.cpp | 19 +++++++++++++++++++ src/oatpp/web/mime/ContentMappers.hpp | 2 ++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/oatpp/codegen/api_controller/base_define.hpp b/src/oatpp/codegen/api_controller/base_define.hpp index 8362fa34..f9897d8f 100644 --- a/src/oatpp/codegen/api_controller/base_define.hpp +++ b/src/oatpp/codegen/api_controller/base_define.hpp @@ -235,9 +235,9 @@ if(getContentMappers()->getDefaultMapper()) { \ // BODY_DTO MACRO // ------------------------------------------------------ #define OATPP_MACRO_API_CONTROLLER_BODY_DTO(TYPE, PARAM_LIST) \ -const auto& __bodyMapper = getContentMappers()->selectMapper(__request->getHeader(oatpp::web::protocol::http::Header::CONTENT_TYPE)); \ +const auto& __bodyMapper = getContentMappers()->selectMapperForContent(__request->getHeader(oatpp::web::protocol::http::Header::CONTENT_TYPE)); \ if(!__bodyMapper) { \ - throw oatpp::web::protocol::http::HttpError(Status::CODE_500, "ObjectMapper was NOT set. Can't deserialize the request body."); \ + throw oatpp::web::protocol::http::HttpError(Status::CODE_500, "No suitable mapper found to deserialize the request body."); \ } \ const auto& OATPP_MACRO_FIRSTARG PARAM_LIST = \ __request->readBodyToDto(__bodyMapper.get()); \ diff --git a/src/oatpp/web/mime/ContentMappers.cpp b/src/oatpp/web/mime/ContentMappers.cpp index f5c334d1..bdb037ee 100644 --- a/src/oatpp/web/mime/ContentMappers.cpp +++ b/src/oatpp/web/mime/ContentMappers.cpp @@ -160,6 +160,25 @@ std::shared_ptr ContentMappers::selectMapper(const } +std::shared_ptr ContentMappers::selectMapperForContent(const oatpp::String& contentTypeHeader) const { + + std::shared_lock lock(m_mutex); + + if(!contentTypeHeader || contentTypeHeader->empty()) { + return m_defaultMapper; + } + + protocol::http::HeaderValueData values; + protocol::http::Parser::parseHeaderValueData(values, contentTypeHeader, ';'); + + if(values.tokens.empty()) { + return nullptr; + } + + return getMapper(values.tokens.begin()->toString()); + +} + std::shared_ptr ContentMappers::selectMapper(const oatpp::String& acceptHeader) const { std::shared_lock lock(m_mutex); diff --git a/src/oatpp/web/mime/ContentMappers.hpp b/src/oatpp/web/mime/ContentMappers.hpp index 5715ec40..a8b5233c 100644 --- a/src/oatpp/web/mime/ContentMappers.hpp +++ b/src/oatpp/web/mime/ContentMappers.hpp @@ -69,6 +69,8 @@ public: std::shared_ptr getMapper(const oatpp::String& contentType) const; std::shared_ptr getDefaultMapper() const; + std::shared_ptr selectMapperForContent(const oatpp::String& contentTypeHeader) const; + std::shared_ptr selectMapper(const oatpp::String& acceptHeader) const; std::shared_ptr selectMapper(const std::vector& acceptableContentTypes) const;