From 97d759711247cdd69cc48bba6ba7d427ea2ef277 Mon Sep 17 00:00:00 2001 From: Leonid Stryzhevskyi Date: Mon, 15 Nov 2021 04:47:16 +0200 Subject: [PATCH] Update 1.3.0.md --- changelog/1.3.0.md | 134 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) diff --git a/changelog/1.3.0.md b/changelog/1.3.0.md index 71dc67bb..6d36f2e4 100644 --- a/changelog/1.3.0.md +++ b/changelog/1.3.0.md @@ -9,6 +9,9 @@ Contents: - [The New oatpp::String](#the-new-oatppstring) - [ConnectionPool::get() Timeout](#connectionpoolget-timeout) - [JSON Serializer Escape Flags](#json-serializer-escape-flags) +- [Headers Stored In unordered_multimap](#headers-stored-in-unordered_multimap) +- [QueryParameters Stored In unordered_multimap](#queryparameters-stored-in-unordered_multimap) +- [Polymorphic DTO_FIELD](#polymorphic-dto_field) - [ConnectionMonitor](#connectionmonitor) - [Request Data Bundle](#request-data-bundle) - [ConnectionProviderSwitch](#connectionproviderswitch) @@ -146,6 +149,137 @@ Output: res='"https://oatpp.io/"' # solidus isn't escaped ``` +## Headers Stored In unordered_multimap + +Headers are now stored using [std::unordered_multimap](https://en.cppreference.com/w/cpp/container/unordered_multimap). + +Put multiple headers: + +```cpp +auto response = createResponse(Status::CODE_200, ""); +response->putHeader("Set-Cookie", "..."); +response->putHeader("Set-Cookie", "..."); +return response; +``` + +Log all "Set-Cookie" headers: + +```cpp + const auto& map = headers.getAll(); + auto bucket = map.bucket("Set-Cookie"); + auto bucketBegin = map.begin(bucket); + auto bucketEnd = map.end(bucket); + + for(auto it = bucketBegin; it != bucketEnd; it ++) { + oatpp::String value = it->second.toString(); + OATPP_LOGD("Header", "Set-Cookie: %s", value->c_str()); + } +``` + +## QueryParameters Stored In unordered_multimap + +QueryParameters are now stored using [std::unordered_multimap](https://en.cppreference.com/w/cpp/container/unordered_multimap). + +Log all entries of "userId" query parameter: + +```cpp + const auto& map = request->getQueryParameters().getAll(); + auto bucket = map.bucket("userId"); + auto bucketBegin = map.begin(bucket); + auto bucketEnd = map.end(bucket); + + for(auto it = bucketBegin; it != bucketEnd; it ++) { + oatpp::String value = it->second.toString(); + OATPP_LOGD("QueryParameter", "userId: %s", value->c_str()); + } +``` + +## Polymorphic DTO_FIELD + +Now, when used inside of a DTO, we can specify exact types that `oatpp::Any` can store by specifying `DTO_FIELD_TYPE_SELECTOR`: + +```cpp +/* Possible type of a DTO_FIELD */ +class ClassA : public oatpp::DTO { + + DTO_INIT(ClassA, DTO) + + DTO_FIELD(String, value); + +}; + +/* Possible type of a DTO_FIELD */ +class ClassB : public oatpp::DTO { + + DTO_INIT(ClassB, DTO) + + DTO_FIELD(Vector, values); + +}; + +/* enum of possible DTO_FIELD types */ +ENUM(ClassType, v_int32, + VALUE(CLASS_TYPE_A, 0), + VALUE(CLASS_TYPE_B, 1) +) + +/* our DTO */ +class ResponseDto : public oatpp::DTO { + + DTO_INIT(ResponseDto, DTO) + + /* type control field */ + DTO_FIELD(Enum::AsString, payloadType); + + /* polymorphic field */ + DTO_FIELD(Any, payload); + + /* type selector */ + DTO_FIELD_TYPE_SELECTOR(payload) { + if(!payloadType) return Void::Class::getType(); + switch (*payloadType) { + case ClassType::CLASS_TYPE_A: return Object::Class::getType(); + case ClassType::CLASS_TYPE_B: return Object::Class::getType(); + } + } + +}; + +... + +/* send polymorphic payload to client */ +ENDPOINT("GET", "payload", getPayload) { + + auto payload = ClassB::createShared(); + payload->values = {"value1", "value2", "value3"}; + + auto r = ResponseDto::createShared(); + r->payloadType = ClassType::CLASS_TYPE_B; + r->payload = payload; + + return createDtoResponse(Status::CODE_200, r); + +} + +/* receive polymorphic payload from client */ +ENDPOINT("POST", "payload", postPayload, + BODY_DTO(oatpp::Object, r)) +{ + + /* check type-control field and retrieve value of the corresponding type */ + if(r->payloadType == ClassType::CLASS_TYPE_B) { + auto payload = r->payload.retrieve>(); + for(auto& value : *payload->values) { + OATPP_LOGD("VALUE", "%s", value->c_str()); + } + } + + return createResponse(Status::CODE_200, "OK"); + +} + +``` + ## ConnectionMonitor `oatpp::network::monitor::ConnectionMonitor` is a middleman who's able to monitor provided connections and close those ones that not satisfy selected rules.