Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
Frameworks/WebService/Server/VariantValue.inl
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#include <tuple>
5
6#include "Stroika/Foundation/IO/Network/HTTP/ClientErrorException.h"
7
8#include "Stroika/Frameworks/WebService/Server/Basic.h"
9
10namespace Stroika::Frameworks::WebService::Server::VariantValue {
11
12 /*
13 ********************************************************************************
14 ****************** WebService::Server::VariantValue::ApplyArgs *****************
15 ********************************************************************************
16 */
17 namespace STROIKA_PRIVATE_ {
18 // use tuple_cat to put all the args together (but in a tuple) and then apply on the function to expand the args to call f
19 template <typename IGNORED_F_RETURN_TYPE>
20 inline auto mkArgsTuple_ (const Iterable<VariantValue>& variantValueArgs, const DataExchange::ObjectVariantMapper& objVarMapper,
21 [[maybe_unused]] const function<IGNORED_F_RETURN_TYPE (void)>& f)
22 {
23 Require (variantValueArgs.size () == 0);
24 return make_tuple ();
25 }
26 template <typename IGNORED_F_RETURN_TYPE, typename SINGLE_ARG>
27 inline auto mkArgsTuple_ (const Iterable<VariantValue>& variantValueArgs, const DataExchange::ObjectVariantMapper& objVarMapper,
28 [[maybe_unused]] const function<IGNORED_F_RETURN_TYPE (SINGLE_ARG)>& f)
29 {
30 Require (variantValueArgs.size () == 1);
31 return make_tuple (objVarMapper.ToObject<SINGLE_ARG> (variantValueArgs.Nth (0)));
32 }
33 template <typename IGNORED_F_RETURN_TYPE, typename ARG_FIRST, typename... REST_ARG_TYPES>
34 inline auto mkArgsTuple_ (const Iterable<VariantValue>& variantValueArgs, const DataExchange::ObjectVariantMapper& objVarMapper,
35 [[maybe_unused]] const function<IGNORED_F_RETURN_TYPE (ARG_FIRST, REST_ARG_TYPES...)>& f)
36 {
37 Require (variantValueArgs.size () == sizeof...(REST_ARG_TYPES) + 1);
38 return tuple_cat (mkArgsTuple_ (variantValueArgs.Take (1), objVarMapper, function<IGNORED_F_RETURN_TYPE (ARG_FIRST)>{}),
39 mkArgsTuple_ (variantValueArgs.Skip (1), objVarMapper, function<IGNORED_F_RETURN_TYPE (REST_ARG_TYPES...)>{}));
40 }
41 }
42 template <typename RETURN_TYPE, typename... ARG_TYPES>
43 VariantValue ApplyArgs (const Sequence<VariantValue>& variantValueArgs, const DataExchange::ObjectVariantMapper& objVarMapper,
44 const function<RETURN_TYPE (ARG_TYPES...)>& f)
45 {
46 using IO::Network::HTTP::ClientErrorException;
47 Require (variantValueArgs.size () == sizeof...(ARG_TYPES));
48 // exceptions parsing args mean ill-formatted arguments to the webservice, so treat as client errors
49 auto&& args = ClientErrorException::TreatExceptionsAsClientError (
50 [&] () { return STROIKA_PRIVATE_::mkArgsTuple_ (variantValueArgs, objVarMapper, f); });
51 if constexpr (same_as<RETURN_TYPE, void>) {
52 apply (f, args);
53 return VariantValue{};
54 }
55 else {
56 return objVarMapper.FromObject (apply (f, args));
57 }
58 }
59 template <typename RETURN_TYPE, typename... ARG_TYPES>
60 VariantValue ApplyArgs (const Mapping<String, VariantValue>& variantValueArgs, const DataExchange::ObjectVariantMapper& objVarMapper,
61 const Traversal::Iterable<String>& paramNames, const function<RETURN_TYPE (ARG_TYPES...)>& f)
62 {
63 Sequence<VariantValue> vvs;
64 for (const auto& i : paramNames) {
65 vvs += variantValueArgs.LookupValue (i);
66 }
67 return ApplyArgs (vvs, objVarMapper, f);
68 }
69
70 /*
71 ********************************************************************************
72 ******* WebService::Server::VariantValue::PickoutParamValuesFromBody ***********
73 ********************************************************************************
74 */
75 inline Mapping<String, VariantValue> PickoutParamValuesFromBody (Request& request)
76 {
77 return PickoutParamValuesFromBody (request.GetBody (), request.contentType ());
78 }
79
80 /*
81 ********************************************************************************
82 ******** WebService::Server::VariantValue::PickoutParamValuesFromURL ***********
83 ********************************************************************************
84 */
85 inline Mapping<String, VariantValue> PickoutParamValuesFromURL (const Request& request)
86 {
87 return PickoutParamValuesFromURL (request.url ());
88 }
89
90 /*
91 ********************************************************************************
92 ************ WebService::Server::VariantValue::OrderParamValues ****************
93 ********************************************************************************
94 */
95 inline Sequence<VariantValue> OrderParamValues (const Iterable<String>& paramNames, Request& request)
96 {
97 return OrderParamValues (paramNames, PickoutParamValues (request));
98 }
99
100 /*
101 ********************************************************************************
102 ***************** WebService::Server::VariantValue::WriteResponse **************
103 ********************************************************************************
104 */
105 inline void WriteResponse ([[maybe_unused]] Response& response, [[maybe_unused]] const WebServiceMethodDescription& webServiceDescription)
106 {
107 // nothing todo to write empty (void) response
108 }
109
110 /// DEPREACTED.....................................
111
112 /**
113 */
114 // template <typename RETURN_TYPE, typename... IN_ARGS>
115 // void CallFAndWriteConvertedResponse (Response* response, const WebServiceMethodDescription& webServiceDescription, const DataExchange::ObjectVariantMapper& objVarMapper, const function<RETURN_TYPE (IN_ARGS...)>& f, IN_ARGS... inArgs);
116 namespace PRIVATE_ {
117 template <typename RETURN_TYPE>
118 inline void CallFAndWriteConvertedResponse_ (Response* response, const WebServiceMethodDescription& webServiceDescription,
119 const DataExchange::ObjectVariantMapper& objVarMapper,
120 const function<RETURN_TYPE ()>& f, enable_if_t<!same_as<RETURN_TYPE, void>>* = 0)
121 {
122 WriteResponse (*response, webServiceDescription, objVarMapper.FromObject (forward<RETURN_TYPE> (f ())));
123 }
124 template <typename RETURN_TYPE>
125 inline void CallFAndWriteConvertedResponse_ (Response* response, const WebServiceMethodDescription& webServiceDescription,
126 const DataExchange::ObjectVariantMapper& objVarMapper,
127 const function<RETURN_TYPE ()>& f, enable_if_t<same_as<RETURN_TYPE, void>>* = 0)
128 {
129 f ();
130 WriteResponse (*response, webServiceDescription);
131 }
132 }
133 template <typename RETURN_TYPE, typename... IN_ARGS>
134 [[deprecated ("Since Stroika v3.0d12 ")]] inline void
135 CallFAndWriteConvertedResponse (Response* response, const WebServiceMethodDescription& webServiceDescription,
136 const DataExchange::ObjectVariantMapper& objVarMapper, const function<RETURN_TYPE (IN_ARGS...)>& f, IN_ARGS... inArgs)
137 {
138 PRIVATE_::CallFAndWriteConvertedResponse_ (response, webServiceDescription, objVarMapper,
139 function<RETURN_TYPE ()>{bind<RETURN_TYPE> (f, forward<IN_ARGS> (inArgs)...)});
140 }
141
142 [[deprecated ("Since Stroika v3.0d12 - use Request&")]] inline Mapping<String, VariantValue> PickoutParamValuesFromBody (Request* request)
143 {
144 RequireNotNull (request);
145 return PickoutParamValuesFromBody (request->GetBody (), request->contentType ());
146 }
147 [[deprecated ("Since Stroika v3.0d12 - use Request&")]] inline Mapping<String, VariantValue> PickoutParamValuesFromURL (const Request* request)
148 {
149 RequireNotNull (request);
150 return PickoutParamValuesFromURL (request->url ());
151 }
152 [[deprecated ("Since Stroika v3.0d12 - use Request&")]] inline Sequence<VariantValue> OrderParamValues (const Iterable<String>& paramNames,
153 Request* request)
154 {
155 return OrderParamValues (paramNames, *request);
156 }
157 [[deprecated ("Since Stroika v3.0d12 - use Response&")]] inline void WriteResponse (Response* response, const WebServiceMethodDescription& webServiceDescription)
158 {
159 WriteResponse (*response, webServiceDescription);
160 }
161 [[deprecated ("Since Stroika v3.0d12 - use Response&")]] inline void
162 WriteResponse (Response* response, const WebServiceMethodDescription& webServiceDescription, const Memory::BLOB& responseValue)
163 {
164 WriteResponse (*response, webServiceDescription, responseValue);
165 }
166 [[deprecated ("Since Stroika v3.0d12 - use Response&")]] inline void
167 WriteResponse (Response* response, const WebServiceMethodDescription& webServiceDescription, const VariantValue& responseValue)
168 {
169 WriteResponse (*response, webServiceDescription, responseValue);
170 }
171
172 [[deprecated ("Since Stroika v3.0d12 - use Request&")]] inline Mapping<String, DataExchange::VariantValue> PickoutParamValues (Request* request)
173 {
174 return PickoutParamValues (*request);
175 }
176
177 template <typename RETURN_TYPE, typename ARG_TYPE_COMBINED>
178 [[deprecated ("Since v3.0d12 - use ObjectRequestHandler::Factory")]] WebServer::RequestHandler
179 mkRequestHandler (const WebServiceMethodDescription& webServiceDescription, const DataExchange::ObjectVariantMapper& objVarMapper,
180 const function<RETURN_TYPE (ARG_TYPE_COMBINED)>& f)
181 {
182 return [=] (WebServer::Message& m) {
183 ExpectedMethod (m.request (), webServiceDescription);
184 if constexpr (same_as<RETURN_TYPE, void>) {
185 f (objVarMapper.ToObject<ARG_TYPE_COMBINED> (CombineWebServiceArgsAsVariantValue (m.rwRequest ())));
186 WriteResponse (m.rwResponse (), webServiceDescription);
187 }
188 else {
189 WriteResponse (m.rwResponse (), webServiceDescription,
190 f (objVarMapper.ToObject<ARG_TYPE_COMBINED> (CombineWebServiceArgsAsVariantValue (m.rwRequest ()))));
191 }
192 };
193 }
194 template <typename RETURN_TYPE, typename... IN_ARGS>
195 [[deprecated ("Since v3.0d12 - use ObjectRequestHandler::Factory")]] WebServer::RequestHandler
196 mkRequestHandler (const WebServiceMethodDescription& webServiceDescription, const DataExchange::ObjectVariantMapper& objVarMapper,
197 const Traversal::Iterable<String>& paramNames, const function<RETURN_TYPE (IN_ARGS...)>& f)
198 {
199 Require (paramNames.size () == sizeof...(IN_ARGS));
200 return [=] (WebServer::Message& m) {
201 ExpectedMethod (m.request (), webServiceDescription);
202 Sequence<VariantValue> args = OrderParamValues (paramNames, m.rwRequest ());
203 Assert (args.size () == paramNames.size ());
204 if constexpr (same_as<RETURN_TYPE, void>) {
205 (void)ApplyArgs (args, objVarMapper, f);
206 WriteResponse (m.rwResponse (), webServiceDescription);
207 }
208 else {
209 WriteResponse (m.rwResponse (), webServiceDescription, ApplyArgs (args, objVarMapper, f));
210 }
211 };
212 }
213 template <typename RETURN_TYPE>
214 [[deprecated ("Since v3.0d12 - use ObjectRequestHandler::Factory")]] WebServer::RequestHandler
215 mkRequestHandler (const WebServiceMethodDescription& webServiceDescription, const DataExchange::ObjectVariantMapper& objVarMapper,
216 const function<RETURN_TYPE (void)>& f)
217 {
218 return [=] (WebServer::Message& m) {
219 ExpectedMethod (m.request (), webServiceDescription);
220 if constexpr (same_as<RETURN_TYPE, void>) {
221 f ();
222 WriteResponse (m.rwResponse (), webServiceDescription);
223 }
224 else {
225 WriteResponse (m.rwResponse (), webServiceDescription, objVarMapper.FromObject (f ()));
226 }
227 };
228 }
229 [[deprecated ("Since v3.0d12 - use ObjectRequestHandler::Factory")]] inline WebServer::RequestHandler
230 mkRequestHandler (const WebServiceMethodDescription& webServiceDescription, const function<Memory::BLOB (WebServer::Message* m)>& f)
231 {
232 return [=] (WebServer::Message& m) {
233 ExpectedMethod (m.request (), webServiceDescription);
234 if (webServiceDescription.fResponseType) {
235 m.rwResponse ().contentType = *webServiceDescription.fResponseType;
236 }
237 m.rwResponse ().write (f (&m));
238 };
239 }
240
241}
#define RequireNotNull(p)
Definition Assertions.h:347
ObjectVariantMapper can be used to map C++ types to and from variant-union types, which can be transp...
nonvirtual VariantValue FromObject(const T &from) const