ContentMappers: proper handling of Content-Type header

This commit is contained in:
Leonid Stryzhevskyi 2024-05-15 18:19:12 +03:00
parent c7a8164c4a
commit 8377409391
3 changed files with 23 additions and 2 deletions

View File

@ -235,9 +235,9 @@ if(getContentMappers()->getDefaultMapper()) { \
// BODY_DTO MACRO // ------------------------------------------------------ // BODY_DTO MACRO // ------------------------------------------------------
#define OATPP_MACRO_API_CONTROLLER_BODY_DTO(TYPE, PARAM_LIST) \ #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) { \ 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 = \ const auto& OATPP_MACRO_FIRSTARG PARAM_LIST = \
__request->readBodyToDto<TYPE>(__bodyMapper.get()); \ __request->readBodyToDto<TYPE>(__bodyMapper.get()); \

View File

@ -160,6 +160,25 @@ std::shared_ptr<data::mapping::ObjectMapper> ContentMappers::selectMapper(const
} }
std::shared_ptr<data::mapping::ObjectMapper> ContentMappers::selectMapperForContent(const oatpp::String& contentTypeHeader) const {
std::shared_lock<std::shared_mutex> 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<data::mapping::ObjectMapper> ContentMappers::selectMapper(const oatpp::String& acceptHeader) const { std::shared_ptr<data::mapping::ObjectMapper> ContentMappers::selectMapper(const oatpp::String& acceptHeader) const {
std::shared_lock<std::shared_mutex> lock(m_mutex); std::shared_lock<std::shared_mutex> lock(m_mutex);

View File

@ -69,6 +69,8 @@ public:
std::shared_ptr<data::mapping::ObjectMapper> getMapper(const oatpp::String& contentType) const; std::shared_ptr<data::mapping::ObjectMapper> getMapper(const oatpp::String& contentType) const;
std::shared_ptr<data::mapping::ObjectMapper> getDefaultMapper() const; std::shared_ptr<data::mapping::ObjectMapper> getDefaultMapper() const;
std::shared_ptr<data::mapping::ObjectMapper> selectMapperForContent(const oatpp::String& contentTypeHeader) const;
std::shared_ptr<data::mapping::ObjectMapper> selectMapper(const oatpp::String& acceptHeader) const; std::shared_ptr<data::mapping::ObjectMapper> selectMapper(const oatpp::String& acceptHeader) const;
std::shared_ptr<data::mapping::ObjectMapper> selectMapper(const std::vector<oatpp::String>& acceptableContentTypes) const; std::shared_ptr<data::mapping::ObjectMapper> selectMapper(const std::vector<oatpp::String>& acceptableContentTypes) const;