Qore RestClient Module Reference 1.10
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
212namespace RestClient {
215
216public:
218 const DataSerializationSupport = {
219%ifndef NoJson
220 "json": MimeTypeJson,
221%endif
222%ifndef NoYaml
223 "yaml": MimeTypeYaml,
224%endif
225%ifndef NoXml
226 "xml": MimeTypeXml,
227 "rawxml": MimeTypeXmlApp,
228%endif
229 "url": MimeTypeFormUrlEncoded,
230 "text": MimeTypeText,
231 "bin": MimeTypeOctetStream,
232 };
233
234 const DeserializeYaml = {
235 "code": "yaml",
236 "in": \parse_yaml(),
237 };
238 const DeserializeXml = {
239 "code": "xml",
240 "arg": True,
241 "in": hash<auto> sub (string xml, reference<string> type) {
242 try {
243 on_success type = "xml";
244 return parse_xmlrpc_value(xml);
245 } catch (hash<ExceptionInfo> ex) {
246 try {
247 on_success type = "rawxml";
248 return parse_xml(xml);
249 } catch () {
250 rethrow;
251 }
252 }
253 },
254 };
255
257 const AcceptList = ...;
258
259
261 const Accept = AcceptList.join(",");
262
264 const AcceptMap = map {$1: True}, AcceptList;
265
267 const Version = "1.7";
268
270 const VersionString = sprintf("Qore-RestClient/%s", RestClient::Version);
271
273 const DefaultHeaders = {
274 "Accept": Accept,
275 "User-Agent": RestClient::VersionString,
276 };
277
279
289 const DataSerializationOptions = {
290 "auto": True,
291%ifndef NoJson
292 "json": True,
293%endif
294%ifndef NoYaml
295 "yaml": True,
296%endif
297%ifndef NoXml
298 "rawxml": True,
299 "xml": True,
300%endif
301 "url": True,
302 "text": True,
303 "bin": True,
304 };
305
307
313 const EncodingSupport = {
314 "gzip": {
315 "ce": "gzip",
316 "func": \gzip(),
317 },
318 "bzip2": {
319 "ce": "bzip2",
320 "func": \bzip2(),
321 },
322 "deflate": {
323 "ce": "deflate",
324 "func": \compress(),
325 },
326 "identity": {
327 "ce": NOTHING,
328 },
329 };
330
332 const CompressionThreshold = 1024;
333
334protected:
335 // headers to send with every request
336 hash<auto> headers;
337 // data serialization code
338 string ds;
339 // serialization content type
340 string sct;
341 // send content encoding hash
342 *hash<auto> seh;
343 // REST schema validator
345 // no_charset option
346 *bool noCharset;
347
348public:
349
351
412 constructor(*hash<auto> opts, *softbool do_not_connect)
413 ;
414
415
417
420
421
423
434 setSerialization(string data = 'auto');
435
436
438
453 setSendEncoding(string enc = 'auto');
454
455
457
472 setContentEncoding(string enc = 'auto');
473
474
476
490 addDefaultHeaders(hash<auto> h);
491
492
494
507 hash<auto> getDefaultHeaders();
508
509
511
525
526
528
538
539
541
582 hash<auto> get(string path, auto body, *reference<hash<auto>> info, *hash<auto> hdr);
583
584
586
626 hash<auto> put(string path, auto body, *reference<hash<auto>> info, *hash<auto> hdr);
627
628
630
670 hash<auto> patch(string path, auto body, *reference<hash<auto>> info, *hash<auto> hdr);
671
672
674
725 hash<auto> post(string path, auto body, *reference<hash<auto>> info, *hash<auto> hdr);
726
727
729
780 hash<auto> del(string path, auto body, *reference<hash<auto>> info, *hash<auto> hdr);
781
782
784
789
790
792 private nothing prepareMsg(string method, string path, reference<auto> body, reference<hash<auto>> hdr,
793 string ct = "Content-Type") {
794 // use {} + ... here to ensure that hdr stays "hash<auto>"
795 hdr = {} + headers + hdr;
796
797 // must get the path from the HTTPClient object if not given in the request
798 if (!path.val() && (*string p = getConnectionPath()))
799 path = p;
800
801 hash<RestRequestClientInfo> req = validator.processRequest(method, path, body, hdr, sct);
802
803 if (exists body);
804
805 }
806
808protected:
809 nothing preparePath(reference<string> path);
810public:
811
812
814
874 hash<auto> doRequest(string m, string path, auto body, *reference<hash<auto>> info, softbool decode_errors = True,
875 *hash<auto> hdr) {
876 prepareMsg(m, path, \body, \hdr);
877
878 on_exit if (exists body);
879
880
881 // prepare path
882 preparePath(\path);
883
884 on_error rethrow $1.err, sprintf("%s (REST URL %y)", $1.desc, getSafeURL());
885
886 return sendAndDecodeResponse(body, m, path, hdr, \info, decode_errors);
887 }
888
890
892 hash<auto> doValidatedRequest(string m, string path, auto body, *reference<hash<auto>> info,
893 softbool decode_errors = True, *hash<auto> hdr) {
894 // use {} + ... here to ensure that hdr stays "hash<auto>"
895 hdr = {} + headers + hdr;
896
897 on_exit if (exists body);
898
899
900 return sendAndDecodeResponse(body, m, path, hdr, \info, decode_errors);
901 }
902
904 private hash<auto> sendAndDecodeResponse(*data body, string m, string path, hash<auto> hdr,
905 *reference<hash<auto>> info, *softbool decode_errors) {
906 hash<auto> h;
907 try {
908 h = send(body, m, path, hdr, False, \info);
909 info."response-code" = h.status_code;
910 } catch (hash<ExceptionInfo> ex) {
911 info."response-code" = info."response-headers".status_code;
912 if (ex.arg) {
913 if (decode_errors && ex.arg.body) {
914 decodeError(ex.arg, \info);
915 ex.arg.deserialized_body = info."response-body";
916 }
917 }
918
919 rethrow ex.err, ex.desc, ex.arg;
920 }
921
922 on_error {
923 if (exists h.body && !exists info."response-body") {
924 info."response-body" = h.body;
925 }
926 }
927
928 return processRestResponse(h, m, path, \info);
929 }
930
932
939protected:
940 hash<auto> processRestResponse(hash<auto> resp, string method, string path, *reference<hash<auto>> info);
941public:
942
943
945protected:
946 static decodeError(hash<auto> h, *reference<hash<auto>> info);
947public:
948
949
951private:
952 static tryDecodeErrorResponse(reference<hash<auto>> h, *reference<hash<auto>> info);
953public:
954
955
956}; // class RestClient
957
959
1001
1002public:
1004 hash<auto> real_opts;
1005
1007 const ConnectionScheme = <ConnectionSchemeInfo>{
1008 "cls": Class::forName("RestConnection"),
1009 "options": HttpConnection::ConnectionScheme.options + {
1010 "content_encoding": <ConnectionOptionInfo>{
1011 "type": "string",
1012 "desc": "this sets the send encoding (if the `send_encoding` option is not set) and the "
1013 "response encoding to request",
1014 "allowed_values": (
1015 <AllowedValueInfo>{
1016 "value": "gzip",
1017 "desc": "use GNU zip encoding ([RFC 1952](https://tools.ietf.org/html/rfc1952))",
1018 }, <AllowedValueInfo>{
1019 "value": "bzip2",
1020 "desc": "use bzip2 encoding",
1021 }, <AllowedValueInfo>{
1022 "value": "deflate",
1023 "desc": "use the deflate algorithm ([RFC 1951](https://tools.ietf.org/html/rfc1951))",
1024 }, <AllowedValueInfo>{
1025 "value": "identity",
1026 "desc": "use no content encoding",
1027 },
1028 ),
1029 },
1030 "data": <ConnectionOptionInfo>{
1031 "type": "string",
1032 "desc": "data serialization options",
1033 "allowed_values": (
1034 <AllowedValueInfo>{
1035 "value": "auto",
1036 "desc": "prefers in this order: `json`, `yaml`, `rawxml`, `xml`, `url`, and `text`",
1037 }, <AllowedValueInfo>{
1038 "value": "bin",
1039 "desc": "for binary message bodies without data serialization",
1040 }, <AllowedValueInfo>{
1041 "value": "json",
1042 "desc": "use JSON serialization",
1043 }, <AllowedValueInfo>{
1044 "value": "rawxml",
1045 "desc": "use raw XML serialization",
1046 }, <AllowedValueInfo>{
1047 "value": "text",
1048 "desc": "use only plain text; no serialization is used",
1049 }, <AllowedValueInfo>{
1050 "value": "url",
1051 "desc": "for URL-encoded message bodies",
1052 }, <AllowedValueInfo>{
1053 "value": "xml",
1054 "desc": "use only XML-RPC serialization",
1055 }, <AllowedValueInfo>{
1056 "value": "yaml",
1057 "desc": "use only YAML serialization",
1058 },
1059 ),
1060 "default_value": "auto",
1061 },
1062 "headers": <ConnectionOptionInfo>{
1063 "type": "hash",
1064 "desc": "an optional hash of headers to send with every request, these can also be "
1065 "overridden in request method calls",
1066 },
1067 "ping_method": <ConnectionOptionInfo>{
1068 "type": "string",
1069 "desc": "The HTTP method to use for an advanced ping; this and `ping_path` must be set to make an "
1070 "HTTP request as a part of the socket polling ping operation; must be a valid HTTP method name",
1071 },
1072 "ping_path": <ConnectionOptionInfo>{
1073 "type": "string",
1074 "desc": "The URI path to use for an advanced ping; this and `ping_method` must be made to make an "
1075 "HTTP request as a part of the socket polling ping operation",
1076 },
1077 "ping_headers": <ConnectionOptionInfo>{
1078 "type": "hash",
1079 "desc": "Any HTTP headers to send when performing an advanced ping operation; ignored if either "
1080 "one of `ping_method` and `ping_path` are not set",
1081 },
1082 "ping_body": <ConnectionOptionInfo>{
1083 "type": "auto",
1084 "desc": "Any message body to send when performing an advanced ping operation; ignored if either "
1085 "one of `ping_method` and `ping_path` are not set or if `ping_method` is `GET`",
1086 },
1087 "send_encoding": <ConnectionOptionInfo>{
1088 "type": "string",
1089 "desc": "this sets the send encoding",
1090 "allowed_values": (
1091 <AllowedValueInfo>{
1092 "value": "gzip",
1093 "desc": "use GNU zip encoding ([RFC 1952](https://tools.ietf.org/html/rfc1952))",
1094 }, <AllowedValueInfo>{
1095 "value": "bzip2",
1096 "desc": "use bzip2 encoding",
1097 }, <AllowedValueInfo>{
1098 "value": "deflate",
1099 "desc": "use the deflate algorithm ([RFC 1951](https://tools.ietf.org/html/rfc1951))",
1100 }, <AllowedValueInfo>{
1101 "value": "identity",
1102 "desc": "use no content encoding",
1103 },
1104 ),
1105 },
1106 "swagger": <ConnectionOptionInfo>{
1107 "type": "file-as-string",
1108 "desc": "the location of a Swagger schema to use for message validation; processed with "
1109 "`FileLocationHandler::getTextFileFromLocation()` "
1110 "(ex: `file:///path/to/swagger-schema.json`); conflicts with `validator`",
1111 "freeform": True,
1112 },
1113 "swagger_base_path": <ConnectionOptionInfo>{
1114 "type": "string",
1115 "desc": "in case a REST validator is used, the base path in the schema can be overridden "
1116 "with this option (applies to any REST validator; not just Swagger validators)",
1117 },
1118 "swagger_lax_parsing": <ConnectionOptionInfo>{
1119 "type": "bool",
1120 "desc": "try to parse invalid Swagger schemas",
1121 },
1122 "validator": <ConnectionOptionInfo>{
1123 "type": "any",
1124 "desc": "an `AbstractRestSchemaValidator` object for REST message validation; conflicts with "
1125 "`swagger`",
1126 },
1127 },
1128 };
1129
1131 const Options = map {$1: True}, keys ConnectionScheme.options;
1132
1134 const OptionList = keys ConnectionScheme.options;
1135
1137
1150 constructor(string name, string description, string url, hash<auto> attributes = {}, hash<auto> options = {})
1151 ;
1152
1153
1155
1163protected:
1164 RestClient getImpl(bool connect = True, *hash<auto> rtopts);
1165public:
1166
1167
1169
1173 object getPollImpl();
1174
1175
1177
1209 hash<auto> getOptions();
1210
1211
1213 string getType();
1214
1215
1217
1224
1225
1227
1232
1233
1235
1241
1242
1244
1246 static hash<auto> processOptions(*hash<auto> opts);
1247
1249
1251protected:
1253public:
1254
1255
1257protected:
1259public:
1260
1261
1263protected:
1264 hash<ConnectionSchemeInfo> getConnectionSchemeInfoImpl();
1265public:
1266
1267};
1268
1270
1273
1274public:
1275protected:
1277 AbstractPollOperation poller;
1278
1280 bool goal_reached = False;
1281
1283 Mutex m();
1284
1285public:
1286
1288 constructor(AbstractPollOperation poller);
1289
1290
1292
1294 string getGoal();
1295
1296
1298
1300 string getState();
1301
1302
1304
1307
1308
1310 *hash<SocketPollInfo> continuePoll();
1311
1312};
1313};
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
static tryDecodeErrorResponse(reference< hash< auto > > h, *reference< hash< auto > > info)
tries to decode an error response
const VersionString
RestClient Version String.
Definition: RestClient.qm.dox.h:270
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 > 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:892
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...
static decodeError(hash< auto > h, *reference< hash< auto > > info)
decode any REST errors returned if possible
hash< auto > processRestResponse(hash< auto > resp, string method, string path, *reference< hash< auto > > info)
Process the raw REST response received.
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:874
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:792
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:267
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:904
class for REST HTTP connections; returns RestClient::RestClient objects
Definition: RestClient.qm.dox.h:1000
bool hasDataProvider()
returns True, as this connection always returns a data provider with the getDataProvider() method
pingImpl()
performs the internal ping
const OptionList
object connection option list
Definition: RestClient.qm.dox.h:1134
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:1004
const Options
object connection options
Definition: RestClient.qm.dox.h:1131
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:1007
string getType()
returns "rest"
DataProvider::AbstractDataProvider getDataProvider()
returns a data provider object for this connection
REST ping polling class.
Definition: RestClient.qm.dox.h:1272
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:1277
bool goal_reached
Goal reached flag.
Definition: RestClient.qm.dox.h:1280
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:212