Qore RestClient Module Reference 1.10.1
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
216namespace RestClient {
219
220public:
222 const DataSerializationSupport = {
223%ifndef NoJson
224 "json": MimeTypeJson,
225%endif
226%ifndef NoYaml
227 "yaml": MimeTypeYaml,
228%endif
229%ifndef NoXml
230 "xml": MimeTypeXml,
231 "rawxml": MimeTypeXmlApp,
232%endif
233 "url": MimeTypeFormUrlEncoded,
234 "text": MimeTypeText,
235 "bin": MimeTypeOctetStream,
236 };
237
238 const DeserializeYaml = {
239 "code": "yaml",
240 "in": \parse_yaml(),
241 };
242 const DeserializeXml = {
243 "code": "xml",
244 "arg": True,
245 "in": hash<auto> sub (string xml, reference<string> type) {
246 try {
247 on_success type = "xml";
248 return parse_xmlrpc_value(xml);
249 } catch (hash<ExceptionInfo> ex) {
250 try {
251 on_success type = "rawxml";
252 return parse_xml(xml);
253 } catch () {
254 rethrow;
255 }
256 }
257 },
258 };
259
261 const AcceptList = ...;
262
263
265 const Accept = AcceptList.join(",");
266
268 const AcceptMap = map {$1: True}, AcceptList;
269
271 const Version = "1.7";
272
274 const VersionString = sprintf("Qore-RestClient/%s", RestClient::Version);
275
277 const DefaultHeaders = {
278 "Accept": Accept,
279 "User-Agent": RestClient::VersionString,
280 };
281
283
293 const DataSerializationOptions = {
294 "auto": True,
295%ifndef NoJson
296 "json": True,
297%endif
298%ifndef NoYaml
299 "yaml": True,
300%endif
301%ifndef NoXml
302 "rawxml": True,
303 "xml": True,
304%endif
305 "url": True,
306 "text": True,
307 "bin": True,
308 };
309
311
317 const EncodingSupport = {
318 "gzip": {
319 "ce": "gzip",
320 "func": \gzip(),
321 },
322 "bzip2": {
323 "ce": "bzip2",
324 "func": \bzip2(),
325 },
326 "deflate": {
327 "ce": "deflate",
328 "func": \compress(),
329 },
330 "identity": {
331 "ce": NOTHING,
332 },
333 };
334
336 const CompressionThreshold = 1024;
337
338protected:
339 // headers to send with every request
340 hash<auto> headers;
341 // data serialization code
342 string ds;
343 // serialization content type
344 string sct;
345 // send content encoding hash
346 *hash<auto> seh;
347 // REST schema validator
349 // no_charset option
350 *bool noCharset;
351
352public:
353
355
416 constructor(*hash<auto> opts, *softbool do_not_connect)
417 ;
418
419
421
424
425
427
438 setSerialization(string data = 'auto');
439
440
442
457 setSendEncoding(string enc = 'auto');
458
459
461
476 setContentEncoding(string enc = 'auto');
477
478
480
494 addDefaultHeaders(hash<auto> h);
495
496
498
511 hash<auto> getDefaultHeaders();
512
513
515
529
530
532
542
543
545
586 hash<auto> get(string path, auto body, *reference<hash<auto>> info, *hash<auto> hdr);
587
588
590
630 hash<auto> put(string path, auto body, *reference<hash<auto>> info, *hash<auto> hdr);
631
632
634
674 hash<auto> patch(string path, auto body, *reference<hash<auto>> info, *hash<auto> hdr);
675
676
678
729 hash<auto> post(string path, auto body, *reference<hash<auto>> info, *hash<auto> hdr);
730
731
733
784 hash<auto> del(string path, auto body, *reference<hash<auto>> info, *hash<auto> hdr);
785
786
788
793
794
796 private nothing prepareMsg(string method, string path, reference<auto> body, reference<hash<auto>> hdr,
797 string ct = "Content-Type") {
798 // use {} + ... here to ensure that hdr stays "hash<auto>"
799 hdr = {} + headers + hdr;
800
801 // must get the path from the HTTPClient object if not given in the request
802 if (!path.val() && (*string p = getConnectionPath()))
803 path = p;
804
805 hash<RestRequestClientInfo> req = validator.processRequest(method, path, body, hdr, sct);
806
807 if (exists body);
808
809 }
810
812protected:
813 nothing preparePath(reference<string> path);
814public:
815
816
818
878 hash<auto> doRequest(string m, string path, auto body, *reference<hash<auto>> info, softbool decode_errors = True,
879 *hash<auto> hdr) {
880 prepareMsg(m, path, \body, \hdr);
881
882 on_exit if (exists body);
883
884
885 // prepare path
886 preparePath(\path);
887
888 on_error {
889 string url = getSafeURL();
890 if (path =~ /^\//) {
891 url += path[1..];
892 } else {
893 url += path;
894 }
895 rethrow $1.err, sprintf("%s (REST URL %y)", $1.desc, url);
896 }
897
898 return sendAndDecodeResponse(body, m, path, hdr, \info, decode_errors);
899 }
900
902
904 hash<auto> doValidatedRequest(string m, string path, auto body, *reference<hash<auto>> info,
905 softbool decode_errors = True, *hash<auto> hdr) {
906 // use {} + ... here to ensure that hdr stays "hash<auto>"
907 hdr = {} + headers + hdr;
908
909 on_exit if (exists body);
910
911
912 return sendAndDecodeResponse(body, m, path, hdr, \info, decode_errors);
913 }
914
916 private hash<auto> sendAndDecodeResponse(*data body, string m, string path, hash<auto> hdr,
917 *reference<hash<auto>> info, *softbool decode_errors) {
918 hash<auto> h;
919 try {
920 h = send(body, m, path, hdr, False, \info);
921 info."response-code" = h.status_code;
922 } catch (hash<ExceptionInfo> ex) {
923 info."response-code" = info."response-headers".status_code;
924 if (ex.arg) {
925 if (decode_errors && ex.arg.body) {
926 decodeError(ex.arg, \info);
927 ex.arg.deserialized_body = info."response-body";
928 }
929 }
930
931 rethrow ex.err, ex.desc, ex.arg;
932 }
933
934 on_error {
935 if (exists h.body && !exists info."response-body") {
936 info."response-body" = h.body;
937 }
938 }
939
940 return processRestResponse(h, m, path, \info);
941 }
942
944
951protected:
952 hash<auto> processRestResponse(hash<auto> resp, string method, string path, *reference<hash<auto>> info);
953public:
954
955
957protected:
958 static decodeError(hash<auto> h, *reference<hash<auto>> info);
959public:
960
961
963private:
964 static tryDecodeErrorResponse(reference<hash<auto>> h, *reference<hash<auto>> info);
965public:
966
967
968}; // class RestClient
969
971
1013
1014public:
1016 hash<auto> real_opts;
1017
1019 const ConnectionScheme = <ConnectionSchemeInfo>{
1020 "cls": Class::forName("RestConnection"),
1021 "options": HttpConnection::ConnectionScheme.options + {
1022 "content_encoding": <ConnectionOptionInfo>{
1023 "type": "string",
1024 "desc": "this sets the send encoding (if the `send_encoding` option is not set) and the "
1025 "response encoding to request",
1026 "allowed_values": (
1027 <AllowedValueInfo>{
1028 "value": "gzip",
1029 "desc": "use GNU zip encoding ([RFC 1952](https://tools.ietf.org/html/rfc1952))",
1030 }, <AllowedValueInfo>{
1031 "value": "bzip2",
1032 "desc": "use bzip2 encoding",
1033 }, <AllowedValueInfo>{
1034 "value": "deflate",
1035 "desc": "use the deflate algorithm ([RFC 1951](https://tools.ietf.org/html/rfc1951))",
1036 }, <AllowedValueInfo>{
1037 "value": "identity",
1038 "desc": "use no content encoding",
1039 },
1040 ),
1041 },
1042 "data": <ConnectionOptionInfo>{
1043 "type": "string",
1044 "desc": "data serialization options",
1045 "allowed_values": (
1046 <AllowedValueInfo>{
1047 "value": "auto",
1048 "desc": "prefers in this order: `json`, `yaml`, `rawxml`, `xml`, `url`, and `text`",
1049 }, <AllowedValueInfo>{
1050 "value": "bin",
1051 "desc": "for binary message bodies without data serialization",
1052 }, <AllowedValueInfo>{
1053 "value": "json",
1054 "desc": "use JSON serialization",
1055 }, <AllowedValueInfo>{
1056 "value": "rawxml",
1057 "desc": "use raw XML serialization",
1058 }, <AllowedValueInfo>{
1059 "value": "text",
1060 "desc": "use only plain text; no serialization is used",
1061 }, <AllowedValueInfo>{
1062 "value": "url",
1063 "desc": "for URL-encoded message bodies",
1064 }, <AllowedValueInfo>{
1065 "value": "xml",
1066 "desc": "use only XML-RPC serialization",
1067 }, <AllowedValueInfo>{
1068 "value": "yaml",
1069 "desc": "use only YAML serialization",
1070 },
1071 ),
1072 "default_value": "auto",
1073 },
1074 "headers": <ConnectionOptionInfo>{
1075 "type": "hash",
1076 "desc": "an optional hash of headers to send with every request, these can also be "
1077 "overridden in request method calls",
1078 },
1079 "ping_method": <ConnectionOptionInfo>{
1080 "type": "string",
1081 "desc": "The HTTP method to use for an advanced ping; this and `ping_path` must be set to make an "
1082 "HTTP request as a part of the socket polling ping operation; must be a valid HTTP method name",
1083 },
1084 "ping_path": <ConnectionOptionInfo>{
1085 "type": "string",
1086 "desc": "The URI path to use for an advanced ping; this and `ping_method` must be made to make an "
1087 "HTTP request as a part of the socket polling ping operation",
1088 },
1089 "ping_headers": <ConnectionOptionInfo>{
1090 "type": "hash",
1091 "desc": "Any HTTP headers to send when performing an advanced ping operation; ignored if either "
1092 "one of `ping_method` and `ping_path` are not set",
1093 },
1094 "ping_body": <ConnectionOptionInfo>{
1095 "type": "auto",
1096 "desc": "Any message body to send when performing an advanced ping operation; ignored if either "
1097 "one of `ping_method` and `ping_path` are not set or if `ping_method` is `GET`",
1098 },
1099 "send_encoding": <ConnectionOptionInfo>{
1100 "type": "string",
1101 "desc": "this sets the send encoding",
1102 "allowed_values": (
1103 <AllowedValueInfo>{
1104 "value": "gzip",
1105 "desc": "use GNU zip encoding ([RFC 1952](https://tools.ietf.org/html/rfc1952))",
1106 }, <AllowedValueInfo>{
1107 "value": "bzip2",
1108 "desc": "use bzip2 encoding",
1109 }, <AllowedValueInfo>{
1110 "value": "deflate",
1111 "desc": "use the deflate algorithm ([RFC 1951](https://tools.ietf.org/html/rfc1951))",
1112 }, <AllowedValueInfo>{
1113 "value": "identity",
1114 "desc": "use no content encoding",
1115 },
1116 ),
1117 },
1118 "swagger": <ConnectionOptionInfo>{
1119 "type": "file-as-string",
1120 "desc": "the location of a Swagger schema to use for message validation; processed with "
1121 "`FileLocationHandler::getTextFileFromLocation()` "
1122 "(ex: `file:///path/to/swagger-schema.json`); conflicts with `validator`",
1123 "freeform": True,
1124 },
1125 "swagger_base_path": <ConnectionOptionInfo>{
1126 "type": "string",
1127 "desc": "in case a REST validator is used, the base path in the schema can be overridden "
1128 "with this option (applies to any REST validator; not just Swagger validators)",
1129 },
1130 "swagger_lax_parsing": <ConnectionOptionInfo>{
1131 "type": "bool",
1132 "desc": "try to parse invalid Swagger schemas",
1133 },
1134 "validator": <ConnectionOptionInfo>{
1135 "type": "any",
1136 "desc": "an `AbstractRestSchemaValidator` object for REST message validation; conflicts with "
1137 "`swagger`",
1138 },
1139 },
1140 };
1141
1143 const Options = map {$1: True}, keys ConnectionScheme.options;
1144
1146 const OptionList = keys ConnectionScheme.options;
1147
1149
1162 constructor(string name, string description, string url, hash<auto> attributes = {}, hash<auto> options = {})
1163 ;
1164
1165
1167
1175protected:
1176 RestClient getImpl(bool connect = True, *hash<auto> rtopts);
1177public:
1178
1179
1181
1185 object getPollImpl();
1186
1187
1189
1221 hash<auto> getOptions();
1222
1223
1225 string getType();
1226
1227
1229
1236
1237
1239
1244
1245
1247
1253
1254
1256
1258 static hash<auto> processOptions(*hash<auto> opts);
1259
1261
1263protected:
1265public:
1266
1267
1269protected:
1271public:
1272
1273
1275protected:
1276 hash<ConnectionSchemeInfo> getConnectionSchemeInfoImpl();
1277public:
1278
1279};
1280
1282
1285
1286public:
1287protected:
1289 AbstractPollOperation poller;
1290
1292 bool goal_reached = False;
1293
1295 Mutex m();
1296
1297public:
1298
1300 constructor(AbstractPollOperation poller);
1301
1302
1304
1306 string getGoal();
1307
1308
1310
1312 string getState();
1313
1314
1316
1319
1320
1322 *hash<SocketPollInfo> continuePoll();
1323
1324};
1325};
hash< auto > patch(string path, auto body, *reference< hash< auto > > info, *hash< auto > hdr)
sends an HTTP PATCH request to the REST server and returns the response
const VersionString
RestClient Version String.
Definition: RestClient.qm.dox.h:274
constructor(*hash< auto > opts, *softbool do_not_connect)
calls the base class HTTPClient constructor and optionally connects to the REST server
hash< auto > post(string path, auto body, *reference< hash< auto > > info, *hash< auto > hdr)
sends an HTTP POST request to the REST server and returns the response
hash< auto > get(string path, auto body, *reference< hash< auto > > info, *hash< auto > hdr)
sends an HTTP GET request to the REST server and returns the response
setContentEncoding(string enc='auto')
sets the request and desired response encoding for the object; see EncodingSupport for valid options
nothing preparePath(reference< string > path)
sets up the path for the HTTP request URI
hash< auto > getDefaultHeaders()
returns the hash of default headers to sent in all requests
hash< auto > del(string path, auto body, *reference< hash< auto > > info, *hash< auto > hdr)
sends an HTTP DELETE request to the REST server and returns the response
hash< auto > put(string path, auto body, *reference< hash< auto > > info, *hash< auto > hdr)
sends an HTTP PUT request to the REST server and returns the response
RestSchemaValidator::AbstractRestSchemaValidator getValidator()
returns the current validator object
setSerialization(string data='auto')
change the serialization option for the object; see DataSerializationOptions for valid options
clearConnectionPath()
Clears the connection path when a validator is present that manages the URI path.
setSendEncoding(string enc='auto')
change the data content encoding (compression) option for the object; see EncodingSupport for valid o...
hash< auto > doRequest(string m, string path, auto body, *reference< hash< auto > > info, softbool decode_errors=True, *hash< auto > hdr)
sends an HTTP request to the REST server and returns the response
Definition: RestClient.qm.dox.h:878
addDefaultHeaders(hash< auto > h)
adds default headers to each request; these headers will be sent in all requests but can be overridde...
private nothing prepareMsg(string method, string path, reference< auto > body, reference< hash< auto > > hdr, string ct="Content-Type")
sets up the Content-Type header and encodes any body for sending
Definition: RestClient.qm.dox.h:796
string getSerialization()
returns the current data serialization format currently in effect for the object (see DataSerializati...
*string getSendEncoding()
returns the current data content encoding (compression) object or NOTHING if no encoding option is se...
const Version
RestClient Version.
Definition: RestClient.qm.dox.h:271
class for REST HTTP connections; returns RestClient::RestClient objects
Definition: RestClient.qm.dox.h:1012
bool hasDataProvider()
returns True, as this connection always returns a data provider with the getDataProvider() method
RestClient getImpl(bool connect=True, *hash< auto > rtopts)
returns a RestClient object
hash< auto > real_opts
real options used when creating an object
Definition: RestClient.qm.dox.h:1016
DataProvider::AbstractDataProvider getDataProvider()
returns a data provider object for this connection
Qore::AbstractPollOperation startPollConnect()
Called to start a non-blocking polling ping operation on the remote REST server.
const Options
object connection options
Definition: RestClient.qm.dox.h:1143
hash< ConnectionSchemeInfo > getConnectionSchemeInfoImpl()
Returns the ConnectionSchemeInfo hash for this object.
string getType()
returns "rest"
hash< auto > getOptions()
gets options
const ConnectionScheme
Connection entry info.
Definition: RestClient.qm.dox.h:1019
object getPollImpl()
Returns an unconnected object for a non-blocking poll operation.
constructor(string name, string description, string url, hash< auto > attributes={}, hash< auto > options={})
creates the RestConnection connection object
const OptionList
object connection option list
Definition: RestClient.qm.dox.h:1146
static hash< auto > processOptions(*hash< auto > opts)
processes options for the constructor
setChildCapabilities()
Sets child data provider capabilities.
pingImpl()
performs the internal ping
REST ping polling class.
Definition: RestClient.qm.dox.h:1284
constructor(AbstractPollOperation poller)
Creates the object with the send/receive poller.
AbstractPollOperation poller
The polling object.
Definition: RestClient.qm.dox.h:1289
Mutex m()
Lock for atomicity.
bool goalReached()
Returns True when the goal as been reached.
string getGoal()
Returns the goal.
bool goal_reached
Goal reached flag.
Definition: RestClient.qm.dox.h:1292
*hash< SocketPollInfo > continuePoll()
Returns a hash to be used for I/O polling or NOTHING in case the poll operation is complete.
string getState()
Returns the current state.
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:216
hash< auto > processRestResponse(hash< auto > resp, string method, string path, *reference< hash< auto > > info)
Process the raw REST response received.
RestClient::RestClient Qore::HTTPClient doValidatedRequest(string m, string path, auto body, *reference< hash< auto > > info, softbool decode_errors=True, *hash< auto > hdr)
The same as doRequest() except no schema validation is performed on the request.
Definition: RestClient.qm.dox.h:904
private hash< auto > sendAndDecodeResponse(*data body, string m, string path, hash< auto > hdr, *reference< hash< auto > > info, *softbool decode_errors)
sends the outgoing HTTP message and recodes the response to data
Definition: RestClient.qm.dox.h:916