Qore RestClient Module Reference 1.9.2
Loading...
Searching...
No Matches
RestClient.qm.dox.h
1// -*- mode: c++; indent-tabs-mode: nil -*-
3
4/* RestClient.qm Copyright (C) 2013 - 2023 Qore Technologies, s.r.o.
5
6 Permission is hereby granted, free of charge, to any person obtaining a
7 copy of this software and associated documentation files (the "Software"),
8 to deal in the Software without restriction, including without limitation
9 the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 and/or sell copies of the Software, and to permit persons to whom the
11 Software is furnished to do so, subject to the following conditions:
12
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
15
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 DEALINGS IN THE SOFTWARE.
23*/
24
25// minimum qore version
26
27// require type definitions everywhere
28
29// enable all warnings
30
31// don't use "$" for vars, members, and methods, assume local variable scope
32
33
34
35
36
37
38}
39
40/* Version History - see below in docs
41*/
42
204namespace RestClient {
207
208public:
210 const DataSerializationSupport = {
211%ifndef NoJson
212 "json": MimeTypeJson,
213%endif
214%ifndef NoYaml
215 "yaml": MimeTypeYaml,
216%endif
217%ifndef NoXml
218 "xml": MimeTypeXml,
219 "rawxml": MimeTypeXmlApp,
220%endif
221 "url": MimeTypeFormUrlEncoded,
222 "text": MimeTypeText,
223 "bin": MimeTypeOctetStream,
224 };
225
226 const DeserializeYaml = {
227 "code": "yaml",
228 "in": \parse_yaml(),
229 };
230 const DeserializeXml = {
231 "code": "xml",
232 "arg": True,
233 "in": hash<auto> sub (string xml, reference<string> type) {
234 try {
235 on_success type = "xml";
236 return parse_xmlrpc_value(xml);
237 } catch (hash<ExceptionInfo> ex) {
238 try {
239 on_success type = "rawxml";
240 return parse_xml(xml);
241 } catch () {
242 rethrow;
243 }
244 }
245 },
246 };
247
249 const AcceptList = ...;
250
251
253 const Accept = AcceptList.join(",");
254
256 const AcceptMap = map {$1: True}, AcceptList;
257
259 const Version = "1.7";
260
262 const VersionString = sprintf("Qore-RestClient/%s", RestClient::Version);
263
265 const DefaultHeaders = {
266 "Accept": Accept,
267 "User-Agent": RestClient::VersionString,
268 };
269
271
281 const DataSerializationOptions = {
282 "auto": True,
283%ifndef NoJson
284 "json": True,
285%endif
286%ifndef NoYaml
287 "yaml": True,
288%endif
289%ifndef NoXml
290 "rawxml": True,
291 "xml": True,
292%endif
293 "url": True,
294 "text": True,
295 "bin": True,
296 };
297
299
305 const EncodingSupport = {
306 "gzip": {
307 "ce": "gzip",
308 "func": \gzip(),
309 },
310 "bzip2": {
311 "ce": "bzip2",
312 "func": \bzip2(),
313 },
314 "deflate": {
315 "ce": "deflate",
316 "func": \compress(),
317 },
318 "identity": {
319 "ce": NOTHING,
320 },
321 };
322
324 const CompressionThreshold = 1024;
325
326protected:
327 // headers to send with every request
328 hash<auto> headers;
329 // data serialization code
330 string ds;
331 // serialization content type
332 string sct;
333 // send content encoding hash
334 *hash<auto> seh;
335 // REST schema validator
337 // no_charset option
338 *bool noCharset;
339
340public:
341
343
404 constructor(*hash<auto> opts, *softbool do_not_connect) : HTTPClient(opts + ((opts.url || !opts.validator)
405 ? NOTHING
406 ;
407
408
410
412 clearConnectionPath();
413
414
416
427 setSerialization(string data = 'auto');
428
429
431
446 setSendEncoding(string enc = 'auto');
447
448
450
465 setContentEncoding(string enc = 'auto');
466
467
469
483 addDefaultHeaders(hash<auto> h);
484
485
487
500 hash<auto> getDefaultHeaders();
501
502
504
517 *string getSendEncoding();
518
519
521
530 string getSerialization();
531
532
534
575 hash<auto> get(string path, auto body, *reference<hash<auto>> info, *hash<auto> hdr);
576
577
579
619 hash<auto> put(string path, auto body, *reference<hash<auto>> info, *hash<auto> hdr);
620
621
623
663 hash<auto> patch(string path, auto body, *reference<hash<auto>> info, *hash<auto> hdr);
664
665
667
718 hash<auto> post(string path, auto body, *reference<hash<auto>> info, *hash<auto> hdr);
719
720
722
773 hash<auto> del(string path, auto body, *reference<hash<auto>> info, *hash<auto> hdr);
774
775
777
782
783
785 private nothing prepareMsg(string method, string path, reference<auto> body, reference<hash<auto>> hdr,
786 string ct = "Content-Type") {
787 // use {} + ... here to ensure that hdr stays "hash<auto>"
788 hdr = {} + headers + hdr;
789
790 // must get the path from the HTTPClient object if not given in the request
791 if (!path.val() && (*string p = getConnectionPath()))
792 path = p;
793
794 hash<RestRequestClientInfo> req = validator.processRequest(method, path, body, hdr, sct);
795
796 if (exists body);
797
798 }
799
801protected:
802 nothing preparePath(reference<string> path);
803public:
804
805
807
867 hash<auto> doRequest(string m, string path, auto body, *reference<hash<auto>> info, softbool decode_errors = True,
868 *hash<auto> hdr) {
869 prepareMsg(m, path, \body, \hdr);
870
871 on_exit if (exists body);
872
873
874 // prepare path
875 preparePath(\path);
876
877 on_error rethrow $1.err, sprintf("%s (REST URL %y)", $1.desc, getSafeURL());
878
879 return sendAndDecodeResponse(body, m, path, hdr, \info, decode_errors);
880 }
881
883
885 hash<auto> doValidatedRequest(string m, string path, auto body, *reference<hash<auto>> info,
886 softbool decode_errors = True, *hash<auto> hdr) {
887 // use {} + ... here to ensure that hdr stays "hash<auto>"
888 hdr = {} + headers + hdr;
889
890 on_exit if (exists body);
891
892
893 return sendAndDecodeResponse(body, m, path, hdr, \info, decode_errors);
894 }
895
897 private hash<auto> sendAndDecodeResponse(*data body, string m, string path, hash<auto> hdr,
898 *reference<hash<auto>> info, *softbool decode_errors) {
899 hash<auto> h;
900 try {
901 h = send(body, m, path, hdr, False, \info);
902 info."response-code" = h.status_code;
903 } catch (hash<ExceptionInfo> ex) {
904 info."response-code" = info."response-headers".status_code;
905 if (ex.arg) {
906 if (decode_errors && ex.arg.body) {
907 decodeError(ex.arg, \info);
908 ex.arg.deserialized_body = info."response-body";
909 }
910 }
911
912 rethrow ex.err, ex.desc, ex.arg;
913 }
914
915 on_error {
916 if (exists h.body && !exists info."response-body") {
917 info."response-body" = h.body;
918 }
919 }
920
921 return processRestResponse(h, m, path, \info);
922 }
923
925
932protected:
933 hash<auto> processRestResponse(hash<auto> resp, string method, string path, *reference<hash<auto>> info);
934public:
935
936
938protected:
939 static decodeError(hash<auto> h, *reference<hash<auto>> info);
940public:
941
942
944private:
945 static tryDecodeErrorResponse(reference<hash<auto>> h, *reference<hash<auto>> info);
946public:
947
948
949}; // class RestClient
950
952
993
994public:
996 hash<auto> real_opts;
997
999 const ConnectionScheme = <ConnectionSchemeInfo>{
1000 "cls": Class::forName("RestConnection"),
1001 "options": HttpConnection::ConnectionScheme.options + {
1002 "content_encoding": <ConnectionOptionInfo>{
1003 "type": "string",
1004 "desc": "this sets the send encoding (if the `send_encoding` option is not set) and the "
1005 "response encoding to request",
1006 "allowed_values": (
1007 <AllowedValueInfo>{
1008 "value": "gzip",
1009 "desc": "use GNU zip encoding ([RFC 1952](https://tools.ietf.org/html/rfc1952))",
1010 }, <AllowedValueInfo>{
1011 "value": "bzip2",
1012 "desc": "use bzip2 encoding",
1013 }, <AllowedValueInfo>{
1014 "value": "deflate",
1015 "desc": "use the deflate algorithm ([RFC 1951](https://tools.ietf.org/html/rfc1951))",
1016 }, <AllowedValueInfo>{
1017 "value": "identity",
1018 "desc": "use no content encoding",
1019 },
1020 ),
1021 },
1022 "data": <ConnectionOptionInfo>{
1023 "type": "string",
1024 "desc": "data serialization options",
1025 "allowed_values": (
1026 <AllowedValueInfo>{
1027 "value": "auto",
1028 "desc": "prefers in this order: `json`, `yaml`, `rawxml`, `xml`, `url`, and `text`",
1029 }, <AllowedValueInfo>{
1030 "value": "bin",
1031 "desc": "for binary message bodies without data serialization",
1032 }, <AllowedValueInfo>{
1033 "value": "json",
1034 "desc": "use JSON serialization",
1035 }, <AllowedValueInfo>{
1036 "value": "rawxml",
1037 "desc": "use raw XML serialization",
1038 }, <AllowedValueInfo>{
1039 "value": "text",
1040 "desc": "use only plain text; no serialization is used",
1041 }, <AllowedValueInfo>{
1042 "value": "url",
1043 "desc": "for URL-encoded message bodies",
1044 }, <AllowedValueInfo>{
1045 "value": "xml",
1046 "desc": "use only XML-RPC serialization",
1047 }, <AllowedValueInfo>{
1048 "value": "yaml",
1049 "desc": "use only YAML serialization",
1050 },
1051 ),
1052 "default_value": "auto",
1053 },
1054 "headers": <ConnectionOptionInfo>{
1055 "type": "hash",
1056 "desc": "an optional hash of headers to send with every request, these can also be "
1057 "overridden in request method calls",
1058 },
1059 "ping_method": <ConnectionOptionInfo>{
1060 "type": "string",
1061 "desc": "The HTTP method to use for an advanced ping; this and `ping_path` must be set to make an "
1062 "HTTP request as a part of the socket polling ping operation; must be a valid HTTP method name",
1063 },
1064 "ping_path": <ConnectionOptionInfo>{
1065 "type": "string",
1066 "desc": "The URI path to use for an advanced ping; this and `ping_method` must be made to make an "
1067 "HTTP request as a part of the socket polling ping operation",
1068 },
1069 "ping_headers": <ConnectionOptionInfo>{
1070 "type": "hash",
1071 "desc": "Any HTTP headers to send when performing an advanced ping operation; ignored if either "
1072 "one of `ping_method` and `ping_path` are not set",
1073 },
1074 "ping_body": <ConnectionOptionInfo>{
1075 "type": "auto",
1076 "desc": "Any message body to send when performing an advanced ping operation; ignored if either "
1077 "one of `ping_method` and `ping_path` are not set or if `ping_method` is `GET`",
1078 },
1079 "send_encoding": <ConnectionOptionInfo>{
1080 "type": "string",
1081 "desc": "this sets the send encoding",
1082 "allowed_values": (
1083 <AllowedValueInfo>{
1084 "value": "gzip",
1085 "desc": "use GNU zip encoding ([RFC 1952](https://tools.ietf.org/html/rfc1952))",
1086 }, <AllowedValueInfo>{
1087 "value": "bzip2",
1088 "desc": "use bzip2 encoding",
1089 }, <AllowedValueInfo>{
1090 "value": "deflate",
1091 "desc": "use the deflate algorithm ([RFC 1951](https://tools.ietf.org/html/rfc1951))",
1092 }, <AllowedValueInfo>{
1093 "value": "identity",
1094 "desc": "use no content encoding",
1095 },
1096 ),
1097 },
1098 "swagger": <ConnectionOptionInfo>{
1099 "type": "string",
1100 "desc": "the location of a Swagger schema to use for message validation; processed with "
1101 "`FileLocationHandler::getTextFileFromLocation()` "
1102 "(ex: `file:///path/to/swagger-schema.json`); conflicts with `validator`",
1103 },
1104 "swagger_base_path": <ConnectionOptionInfo>{
1105 "type": "string",
1106 "desc": "in case a REST validator is used, the base path in the schema can be overridden "
1107 "with this option (applies to any REST validator; not just Swagger validators)",
1108 },
1109 "validator": <ConnectionOptionInfo>{
1110 "type": "any",
1111 "desc": "an `AbstractRestSchemaValidator` object for REST message validation; conflicts with "
1112 "`swagger`",
1113 },
1114 },
1115 };
1116
1118 const Options = map {$1: True}, keys ConnectionScheme.options;
1119
1121 const DefaultOptions = ...;
1122
1123
1125 const OptionList = keys ConnectionScheme.options;
1126
1128
1141 constructor(string name, string description, string url, hash<auto> attributes = {}, hash<auto> options = {})
1142 ;
1143
1144
1146
1154protected:
1155 RestClient getImpl(bool connect = True, *hash<auto> rtopts);
1156public:
1157
1158
1160
1164 object getPollImpl();
1165
1166
1168
1199 hash<auto> getOptions();
1200
1201
1203 *hash<auto> getDefaultOptions();
1204
1205
1207 string getType();
1208
1209
1211
1218
1219
1221
1226
1227
1229
1235
1236
1238
1240 static hash<auto> processOptions(*hash<auto> opts);
1241
1243
1245protected:
1247public:
1248
1249
1251protected:
1253public:
1254
1255
1257protected:
1258 hash<ConnectionSchemeInfo> getConnectionSchemeInfoImpl();
1259public:
1260
1261};
1262
1264
1267
1268public:
1269protected:
1271 AbstractPollOperation poller;
1272
1274 bool goal_reached = False;
1275
1277 Mutex m();
1278
1279public:
1280
1282 constructor(AbstractPollOperation poller);
1283
1284
1286
1288 string getGoal();
1289
1290
1292
1294 string getState();
1295
1296
1298
1301
1302
1304 *hash<SocketPollInfo> continuePoll();
1305
1306};
1307};
const VersionString
RestClient Version String.
Definition: RestClient.qm.dox.h:262
const Version
RestClient Version.
Definition: RestClient.qm.dox.h:259
class for REST HTTP connections; returns RestClient::RestClient objects
Definition: RestClient.qm.dox.h:992
bool hasDataProvider()
returns True, as this connection always returns a data provider with the getDataProvider() method
*hash< auto > getDefaultOptions()
returns default options
pingImpl()
performs the internal ping
const OptionList
object connection option list
Definition: RestClient.qm.dox.h:1125
constructor(string name, string description, string url, hash< auto > attributes={}, hash< auto > options={})
creates the RestConnection connection object
hash< auto > real_opts
real options used when creating an object
Definition: RestClient.qm.dox.h:996
const Options
object connection options
Definition: RestClient.qm.dox.h:1118
const DefaultOptions
default options
Definition: RestClient.qm.dox.h:1121
hash< ConnectionSchemeInfo > getConnectionSchemeInfoImpl()
Returns the ConnectionSchemeInfo hash for this object.
Qore::AbstractPollOperation startPollConnect()
Called to start a non-blocking polling ping operation on the remote REST server.
object getPollImpl()
Returns an unconnected object for a non-blocking poll operation.
setChildCapabilities()
Sets child data provider capabilities.
RestClient getImpl(bool connect=True, *hash< auto > rtopts)
returns a RestClient object
static hash< auto > processOptions(*hash< auto > opts)
processes options for the constructor
hash< auto > getOptions()
gets options
const ConnectionScheme
Connection entry info.
Definition: RestClient.qm.dox.h:999
string getType()
returns "rest"
DataProvider::AbstractDataProvider getDataProvider()
returns a data provider object for this connection
REST ping polling class.
Definition: RestClient.qm.dox.h:1266
constructor(AbstractPollOperation poller)
Creates the object with the send/receive poller.
*hash< SocketPollInfo > continuePoll()
Returns a hash to be used for I/O polling or NOTHING in case the poll operation is complete.
string getGoal()
Returns the goal.
bool goalReached()
Returns True when the goal as been reached.
AbstractPollOperation poller
The polling object.
Definition: RestClient.qm.dox.h:1271
bool goal_reached
Goal reached flag.
Definition: RestClient.qm.dox.h:1274
string getState()
Returns the current state.
Mutex m()
Lock for atomicity.
hash< RestRequestClientInfo > processRequest(string method, string path, auto body, *hash< auto > headers, *softlist< string > content_types)
string type(auto arg)
the RestClient namespace contains all the objects in the RestClient module
Definition: RestClient.qm.dox.h:204