Qore RestHandler Module Reference 1.6.2
Loading...
Searching...
No Matches
RestHandler.qm.dox.h
1// -*- mode: c++; indent-tabs-mode: nil -*-
3
4/* RestHandler.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// use new-style
28
29// require type definitions everywhere
30
31// enable all warnings
32
33
34
475namespace RestHandler {
477
485
486public:
487
488
489protected:
491 hash<auto> cx;
492
494 *hash<auto> ex;
495
497 *hash<auto> ah;
498
500 hash<auto> rhdr;
501
504
505public:
506
508
522 constructor(hash<auto> n_cx, *hash<auto> n_ah);
523
524
526
535 hash<HttpServer::HttpHandlerResponseInfo> getResponseHeaderMessage();
536
537
539
558 nothing recv(hash<auto> v);
559
560
562
567 auto send();
568
569
572
573
576
577
579 setTimeout(timeout n_timeout_ms);
580
581
584
585
587 streamError(hash<auto> n_ex);
588
589
591
600 abstract hash<auto> getResponseHeaderMessageImpl();
601
603
613 abstract nothing recvImpl(hash<auto> v);
614
616
619 abstract auto sendImpl();
620 };
621
624
625public:
626protected:
628 bool deserialized;
629
630public:
631
635 hash<auto> cx, hash<auto> hdr, auto body)
637 cx + (exists body ? {'deserialized': True} : NOTHING), hdr, body);
638
639
642
643
644 // callback method for the response header; this calls @ref RestHandler::AbstractRestStreamRequestHandler::getResponseHeaderMessage() and returns the result
654protected:
655 hash<HttpServer::HttpHandlerResponseInfo> getResponseHeaderMessageImpl();
656public:
657
658
660
670protected:
671 nothing recvImpl(hash<auto> v);
672public:
673
674
676
679protected:
680 auto sendImpl();
681public:
682
683 };
684
687
688public:
690 hash<string, AbstractRestClass> class_hash;
691
693 const RestBasicMethodSet = map {$1: True}, RestHandler::Methods.iterator();
694
695 constructor();
696
697
699 abstract string name();
700
703
704
706
731 *AbstractRestClass subClass(string name, hash<auto> cx, *hash<auto> args);
732
733
735
758 *AbstractRestClass subClassImpl(string name, hash<auto> cx, *hash<auto> args);
759
760
762 hash<HttpServer::HttpHandlerResponseInfo> handleRequest(HttpListenerInterface listener, RestHandler rh,
763 Socket s, *list<string> cl, string mn, hash<auto> cx, *hash<auto> args) {
764 if (!args && cx.body.typeCode() == NT_HASH);
765
766 cx.socketobject = s;
767 if (cl);
768
769
770 // try to mask passwords and sensitive data in args
771 string astr = rh.maskData(sprintf("%y", args));
772 rh.logDebug("REST DBG: class %y: dispatching method %y args: %s", name(), mn, astr);
773 return dispatchStream(listener, rh, s, mn, args, cx);
774 }
775
777 private hash<HttpServer::HttpHandlerResponseInfo> dispatchStream(HttpListenerInterface listener,
778 RestHandler rh, Socket s, string mn, *hash<auto> ah, hash<auto> cx) {
779 string sn = "stream" + mn[0].upr() + mn.substr(1);
781 try {
782 rsh = call_object_method_args(self, sn, (cx, ah));
783 } catch (hash<ExceptionInfo> ex) {
784 if (ex.err == "METHOD-DOES-NOT-EXIST" && ex.desc.find(sn) != -1) {
785 if (cx.hdr."transfer-encoding" == "chunked")
786 cx.body = rh.getMessageBody(s, cx.hdr, NOTHING);
787
788 return cast<hash<HttpHandlerResponseInfo>>(dispatch(rh, mn, ah, cx));
789 }
790 string desc = !cx.debug
791 ? sprintf("%s: %s: %s", get_ex_pos(ex), ex.err, ex.desc)
792 : get_exception_string(ex);
793 rh.logDebug("REST DBG: class %y: stream method %y: %s", name(), sn, desc);
794 rethrow;
795 }
796 try {
797 RestStreamRequest req(rsh, listener, rh, s, cx, cx.hdr, cx.hdr."content-length" ? cx.body : NOTHING);
798 return req.handleRequest();
799 } catch (hash<ExceptionInfo> ex) {
800 // make sure the error is registered with the stream handler
801 if (rsh) {
802 # issue #4291: handle errors here correctly
803 try {
804 rsh.streamError(ex);
805 } catch (hash<ExceptionInfo> ex1) {
806 rh.logError("cannot register error %s: %s with stream handler: %s: %s", ex.err, ex.desc,
807 ex1.err, ex1.desc);
808 }
809 }
810 string desc = !cx.debug
811 ? sprintf("%s: %s: %s", get_ex_pos(ex), ex.err, ex.desc)
812 : get_exception_string(ex);
813 rh.logDebug("REST DBG: class %y: stream method %y: %s", name(), sn, desc);
814 rethrow;
815 }
816 }
817
819
840 private hash<HttpServer::HttpHandlerResponseInfo> dispatch(RestHandler rh, string mn, *hash<auto> ah,
841 hash<auto> cx) {
842 try {
843 return cast<hash<HttpHandlerResponseInfo>>(call_object_method_args(self, mn, (cx, ah)));
844 } catch (hash<ExceptionInfo> ex) {
845 if (ex.err == "METHOD-DOES-NOT-EXIST") {
846 // try to mask passwords in args
847 string astr = rh.maskData(sprintf("%y", ah));
848 rh.logError("DISPATCH-ERROR: cannot dispatch to unimplemented method %y: class %y, args: %s", mn,
849 name(), astr);
850 # see if alternate methods would work
851 list hl = ();
852 # break flag
853 bool brk;
854 foreach hash<auto> mh in (RestHandler::Methods.pairIterator()) {
855 string nmn = mh.value + cx.rest_method;
856 if (self.hasCallableMethod(nmn)) {
857 if (mh.key == cx.hdr.method) {
858 brk = True;
859 break;
860 }
861 hl += mh.key;
862 }
863 }
864 if (!brk) {
865 if (!hl)
866 return cast<hash<HttpHandlerResponseInfo>>(RestHandler::make501("REST class %y (%s) does "
867 "not implement method %y", name(), self.className(),
868 cx.orig_method ? cx.orig_method : mn));
869
870 string ml = foldl $1 + "," + $2, hl;
871 string desc = sprintf("HTTP method %s is unimplemented in REST class %y (%s)", cx.hdr.method,
872 name(), self.className());
873 if (cx.orig_method)
874 desc += sprintf(" REST method %y", cx.orig_method);
875 desc += sprintf(", available methods: %s", ml);
876 return cast<hash<HttpHandlerResponseInfo>>(
878 );
879 }
880 }
881 string desc = !cx.debug
882 ? sprintf("%s: %s: %s", get_ex_pos(ex), ex.err, ex.desc)
883 : get_exception_string(ex);
884 rh.logDebug("REST DBG: class %y: method %y: %s", name(), mn, desc);
885 rethrow;
886 }
887 }
888
890
903protected:
904 hash<HttpServer::HttpHandlerResponseInfo> unknownSubClassError(string cls_name, hash<auto> cx, *hash<auto> ah);
905public:
906
907
909
921protected:
922 *hash<string, bool> doGetPossibleSubClasses(hash<auto> cx, *hash<auto> ah);
923public:
924
925 };
926
928
939
940public:
942 const Err501 = new hash<HttpResponseInfo>({
943 "code": 501,
944 "body": "not implemented",
945 });
946
948 const Methods = {
949 "GET": "get",
950 "POST": "post",
951 "PUT": "put",
952 "DELETE": "del",
953 "OPTIONS": "options",
954 "PATCH": "patch",
955 };
956
957protected:
960
963
964public:
965
967
974 RestSchemaValidator::AbstractRestSchemaValidator validator = new NullRestSchemaValidator())
975 ;
976
977
979
987 RestSchemaValidator::AbstractRestSchemaValidator validator = new NullRestSchemaValidator(logger))
988 ;
989
990
992 string name();
993
994
997
998
1000
1021 auto handleExternalRequest(string method, string path, *hash<auto> body, hash<auto> cx = {});
1022
1023
1025
1054 hash<HttpResponseInfo> handleRequest(HttpListenerInterface listener, Socket s, hash<auto> cx, hash<auto> hdr,
1055 *data b) {
1056 //logDebug("REST DBG: cx: %N", cx);
1057 //logDebug("REST DBG: hdr: %N", hdr);
1058
1059 auto body = b;
1060
1061 // get rest class name
1062 string path = cx.url.path ?? "";
1063
1064 removeRootPath(\path);
1065
1066 hash<RestRequestServerInfo> req;
1067 try {
1068 if (b) {
1069 string bstr = maskData(b.typeCode() == NT_STRING ? trim(b) : sprintf("%y", b));
1070 logDebug("REST DBG: body: %s", bstr);
1071 }
1072
1073 req = validator.parseRequest(hdr.method, path, body, \hdr);
1074 } catch (hash<ExceptionInfo> ex) {
1075 logDebug("REST DBG: %s", get_exception_string(ex));
1076 // return a 400 Bad Request response to encoding, serialization, or validation errors
1077 if (ex.err == "INVALID-ENCODING"
1078 || ex.err == "ENCODING-CONVERSION-ERROR"
1079 || ex.err == "DESERIALIZATION-ERROR"
1080 || ex.err == "SCHEMA-VALIDATION-ERROR")
1081 return AbstractHttpRequestHandler::makeResponse(400, sprintf("%s: %s", ex.err, ex.desc),
1082 errorResponseHeaders(cx));
1083 if (ex.err == "INVALID-METHOD") {
1084 string ml = (foldl $1 + "," + $2, ex.arg) ?? "";
1085 return AbstractHttpRequestHandler::makeResponse(405, sprintf("HTTP method %y is not supported "
1086 "with URI path %y; supported methods: %s", hdr.method, path, ml ?* "<none>"),
1087 errorResponseHeaders(cx) + {"Allow": ml});
1088 }
1089 rethrow;
1090 }
1091
1092 // get object and args
1093 hash<auto> ah = path ? {
1094 "method": req.path,
1095 "params": req.query,
1096 } : {};
1097 //path ? parse_uri_query(path) : {};
1098
1099 *hash<auto> args;
1100 if (ah.params);
1101
1102
1103 // add path args, if any
1104 if (req.path_args);
1105
1106
1107 if (exists body);
1108 else {
1109 body = args;
1110 }
1111
1112 // reflect body in arguments if body is a hash
1113 if (body.typeCode() == NT_HASH);
1114
1115
1116 if (!Methods.(hdr.method))
1117 return AbstractHttpRequestHandler::make400("unsupported HTTP method %y given in REST call %y",
1118 hdr.method, path);
1119
1120 // make method name
1121 string mn;
1122 if (args.action);
1123 else if (body.action);
1124 else {
1125 mn = Methods.(hdr.method);
1126 }
1127
1128 cx.rest_action_method = mn;
1129
1130 // remove leading slash from method name
1131 if (ah.method ==1)
1132 splice ah.method, 0, 1;
1133
1134 // get class chain
1135 *list<string> cl;
1136 if (ah.method);
1137
1138
1139 // make a hash of "accept" values
1140 *string astr = hdr.accept;
1141 hash<auto> aih;
1142 if (astr);
1143 else {
1144 // http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html: If no Accept header field is present, then
1145 # it is assumed that the client accepts all media types
1146 aih."*/*" = True;
1147 }
1148
1149 //logDebug("REST DBG: aih: %y", aih);
1150
1151 // set up context hash
1152 cx += {"hdr": hdr, "body": body, "aih": aih};
1153
1154 // handle call with class
1155 hash<HttpHandlerResponseInfo> rv;
1156
1157 try {
1158 rv = dispatchRequest(listener, s, cl, mn, path, cx, args);
1159 } catch (hash<ExceptionInfo> ex) {
1160 string desc = !cx.debug
1161 ? sprintf("%s: %s: %s", get_ex_pos(ex), ex.err, ex.desc)
1162 : get_exception_string(ex);
1163
1164 logError(desc);
1165 rv = returnRestException(ex);
1166 }
1167
1168 if (!rv.reply_sent);
1169
1170
1171 //logDebug("REST DBG: rv: %N", rv);
1172
1173 return cast<hash<HttpResponseInfo>>(rv);
1174 }
1175
1177
1179protected:
1180 *hash<auto> errorResponseHeaders(hash<auto> cx);
1181public:
1182
1183
1185 private hash<HttpHandlerResponseInfo> dispatchRequest(HttpListenerInterface listener, Socket s,
1186 *list<string> class_list, string method_name, string path, hash<auto> cx, *hash<auto> args) {
1187 AbstractRestClass rcls;
1188
1189 // get initial class
1190 *string cls = shift class_list;
1191
1192 if (!cls);
1193 else {
1194 *AbstractRestClass c = subClass(cls, cx, args);
1195 if (!c) {
1196 // issue #2994: if we are on the last class and there is no "action" argument; see if we can f
1197 # ind an action method instead
1198 if (!class_list && !args.action) {
1199 string mname = sprintf("%s%s%s", method_name, cls[0].upr(), cls[1..]);
1200 if (self.hasCallableMethod(mname)) {
1201 rcls = self;
1202 method_name = mname;
1203 }
1204 }
1205
1206 if (!rcls) {
1207 return unknownSubClassError(cls, cx, args);
1208 }
1209 } else {
1210 rcls = c;
1211 }
1212 }
1213
1214 return rcls.handleRequest(listener, self, s, class_list, method_name, cx, args);
1215 }
1216
1218
1221protected:
1222 hash<HttpHandlerResponseInfo> returnRestException(hash<ExceptionInfo> ex);
1223public:
1224
1225
1227protected:
1228 checkExceptionSerializable(reference<hash<ExceptionInfo>> ex);
1229public:
1230
1231
1233 hash<auto> get(hash<auto> cx, *hash<auto> ah);
1234
1235
1237 removeRootPath(reference<string> path);
1238
1239
1241 requestDeserializationError(hash<auto> hdr, hash<auto> cx, string body);
1242
1243
1245 responseSerializationError(hash<auto> cx, *hash<auto> aih, hash<auto> rv);
1246
1247
1249
1251 logInfo(string fmt);
1252
1253
1255
1257 logError(string fmt);
1258
1259
1261
1263 logDebug(string fmt);
1264
1265
1267 static hash<HttpHandlerResponseInfo> make200(string fmt);
1268
1270 static hash<HttpHandlerResponseInfo> make200(hash<auto> hdr, string fmt);
1271
1273 static hash<HttpHandlerResponseInfo> make400(string fmt);
1274
1276 static hash<HttpHandlerResponseInfo> make400(hash<auto> hdr, string fmt);
1277
1279 static hash<HttpHandlerResponseInfo> makeResponse(int code, auto body, *hash<auto> hdr);
1280
1282 static hash<HttpHandlerResponseInfo> make500(string fmt);
1283
1285 static hash<HttpHandlerResponseInfo> make500(hash<auto> hdr, string fmt);
1286
1288 static hash<HttpHandlerResponseInfo> make501(string fmt);
1289
1291 static hash<HttpHandlerResponseInfo> make501(hash<auto> hdr, string fmt);
1292 };
1293};
1294
1295// private, unexported namespace
1296namespace Priv {
1297 // dumHttpListenerInterface class
1298class DummyListenerInterface : public HttpListenerInterface {
1299
1300public:
1301 addUserThreadContext(hash<auto> uctx);
1302
1303
1304 auto removeUserThreadContext(*string k);
1305
1306
1307 log(string fmt);
1308
1309
1310 logError(string fmt);
1311
1312 };
1313};
static hash< HttpResponseInfo > makeResponse(hash< auto > hdr, int code, binary body)
*data getMessageBody(Socket s, hash< auto > hdr, *data body, bool decode=True)
constructor(HttpListenerInterface listener, AbstractHttpRequestHandler handler, Socket s, hash< auto > cx, hash< auto > hdr, auto body)
AbstractHttpRequestHandler handler
hash< HttpHandlerResponseInfo > handleRequest()
HttpListenerInterface listener
the base abstract class for REST handler classes
Definition: RestHandler.qm.dox.h:686
hash< HttpServer::HttpHandlerResponseInfo > unknownSubClassError(string cls_name, hash< auto > cx, *hash< auto > ah)
returns a 404 Not Found response when a request tries to access an unknown subclass
private hash< HttpServer::HttpHandlerResponseInfo > dispatch(RestHandler rh, string mn, *hash< auto > ah, hash< auto > cx)
this method is called to dispatch requests on the given object
Definition: RestHandler.qm.dox.h:840
abstract string name()
this provides the name of the REST class
private hash< HttpServer::HttpHandlerResponseInfo > dispatchStream(HttpListenerInterface listener, RestHandler rh, Socket s, string mn, *hash< auto > ah, hash< auto > cx)
this method is called to dispatch streamed requests on the given object
Definition: RestHandler.qm.dox.h:777
hash< HttpServer::HttpHandlerResponseInfo > handleRequest(HttpListenerInterface listener, RestHandler rh, Socket s, *list< string > cl, string mn, hash< auto > cx, *hash< auto > args)
this method is called by the RestHandler class to match the right object with incoming requests
Definition: RestHandler.qm.dox.h:762
addClass(AbstractRestClass cls)
adds a REST class to the handler
*AbstractRestClass subClassImpl(string name, hash< auto > cx, *hash< auto > args)
this method will be called to find a sub-class (ie with GET /invoices/1 - if this class represents "i...
*hash< string, bool > doGetPossibleSubClasses(hash< auto > cx, *hash< auto > ah)
returns a set of possible subclasses for a particular request
hash< string, AbstractRestClass > class_hash
class hash: name -> AbstractRestClass
Definition: RestHandler.qm.dox.h:690
*AbstractRestClass subClass(string name, hash< auto > cx, *hash< auto > args)
this method will be called to find a sub-class (ie with GET /invoices/1 - if this class represents "i...
const RestBasicMethodSet
set of REST class method names based on basic HTTP methods
Definition: RestHandler.qm.dox.h:693
the base abstract class for REST stream request handlers
Definition: RestHandler.qm.dox.h:484
hash< auto > rhdr
headers to add in the response
Definition: RestHandler.qm.dox.h:500
auto send()
this method provides the callback method for sending chunked data by calling sendImpl()
abstract auto sendImpl()
abstract callback method for sending chunked data
hash< auto > cx
call context hash
Definition: RestHandler.qm.dox.h:491
nothing recv(hash< auto > v)
this method provides the callback method for receiving chunked data by calling recvImpl()
constructor(hash< auto > n_cx, *hash< auto > n_ah)
creates the object with the given arguments
*int getTimeout()
returns the timeout in milliseconds or NOTHING if no timeout is set
*hash< auto > ah
call argument hash
Definition: RestHandler.qm.dox.h:497
hash< HttpServer::HttpHandlerResponseInfo > getResponseHeaderMessage()
this method returns the response message description hash by calling getResponseHeaderMessageImpl()
bool isPersistent()
returns True if the connection is persistent; this method in the base class returns False by default
abstract hash< auto > getResponseHeaderMessageImpl()
this method should return the response message description hash
*int timeout_ms
socket I/O timeout in milliseconds
Definition: RestHandler.qm.dox.h:503
setTimeout(timeout n_timeout_ms)
sets the internal socket I/O timeout value in ms
streamError(hash< auto > n_ex)
registers stream errors in the send operation with the stream handler if no error is already present
*hash< auto > ex
if an exception is raised in a callback then the exception hash is saved here
Definition: RestHandler.qm.dox.h:494
*code getPersistentClosedNotification()
returns a callable value in case a persistent connection is in progress; NOTHING if not; this method ...
abstract nothing recvImpl(hash< auto > v)
abstract callback method for receiving chunked data
auto handleExternalRequest(string method, string path, *hash< auto > body, hash< auto > cx={})
processes REST API calls outside the HTTP server
responseSerializationError(hash< auto > cx, *hash< auto > aih, hash< auto > rv)
default implementation is empty
static hash< HttpHandlerResponseInfo > make500(hash< auto > hdr, string fmt)
creates a hash for an HTTP 500 error response with the response message body as a string
const Methods
supported HTTP methods
Definition: RestHandler.qm.dox.h:948
RestSchemaValidator::AbstractRestSchemaValidator validator
REST schema validator.
Definition: RestHandler.qm.dox.h:962
removeRootPath(reference< string > path)
default implementation is empty
hash< HttpResponseInfo > handleRequest(HttpListenerInterface listener, Socket s, hash< auto > cx, hash< auto > hdr, *data b)
called by the HTTP server to handle incoming HTTP requests
Definition: RestHandler.qm.dox.h:1054
static hash< HttpHandlerResponseInfo > make501(hash< auto > hdr, string fmt)
creates a hash for an HTTP 501 error response with the response message body as a string
static hash< HttpHandlerResponseInfo > make200(hash< auto > hdr, string fmt)
creates a hash for an HTTP 200 OK error response with the response message body as a string
logInfo(string fmt)
This method is called with informational log messages.
checkExceptionSerializable(reference< hash< ExceptionInfo > > ex)
Recursively ensure that exception arguments are serializable.
static hash< HttpHandlerResponseInfo > make501(string fmt)
creates a hash for an HTTP 501 error response with the response message body as a string
private hash< HttpHandlerResponseInfo > dispatchRequest(HttpListenerInterface listener, Socket s, *list< string > class_list, string method_name, string path, hash< auto > cx, *hash< auto > args)
Dispatches the request and returns the response.
Definition: RestHandler.qm.dox.h:1185
static hash< HttpHandlerResponseInfo > makeResponse(int code, auto body, *hash< auto > hdr)
creates a hash for an HTTP response with the response code and a literal response message body
hash< HttpHandlerResponseInfo > returnRestException(hash< ExceptionInfo > ex)
method that determines how exceptions handling REST requests are returned
logError(string fmt)
This method is called with error log messages.
constructor(*HttpServer::AbstractAuthenticator auth, RestSchemaValidator::AbstractRestSchemaValidator validator=new NullRestSchemaValidator())
create the object optionally with the given HttpServer::AbstractAuthenticator
constructor(Logger::Logger logger, *HttpServer::AbstractAuthenticator auth, RestSchemaValidator::AbstractRestSchemaValidator validator=new NullRestSchemaValidator(logger))
create the object optionally with the given Logger and authenticator
static hash< HttpHandlerResponseInfo > make400(hash< auto > hdr, string fmt)
creates a hash for an HTTP 400 error response with the response message body as a string
logDebug(string fmt)
This method is called with debug log messages.
string name()
returns the name of the root REST class
*hash< auto > errorResponseHeaders(hash< auto > cx)
Retrieves headers for an error response.
setLogger(Logger::Logger logger)
Sets a new logger.
hash< auto > get(hash< auto > cx, *hash< auto > ah)
default get handler for the base handler class
static hash< HttpHandlerResponseInfo > make500(string fmt)
creates a hash for an HTTP 500 error response with the response message body as a string
Logger::Logger logger
logger
Definition: RestHandler.qm.dox.h:959
static hash< HttpHandlerResponseInfo > make200(string fmt)
creates a hash for an HTTP 200 OK error response with the response message body as a string
requestDeserializationError(hash< auto > hdr, hash< auto > cx, string body)
default implementation is empty
static hash< HttpHandlerResponseInfo > make400(string fmt)
creates a hash for an HTTP 400 error response with the response message body as a string
the base class for handling HTTP chunked requests and responses within the RestHandler infrastructure
Definition: RestHandler.qm.dox.h:623
nothing recvImpl(hash< auto > v)
callback method for receiving chunked data; this calls RestHandler::AbstractRestStreamRequestHandler:...
hash< HttpServer::HttpHandlerResponseInfo > getResponseHeaderMessageImpl()
constructor(RestHandler::AbstractRestStreamRequestHandler n_stream, HttpServer::HttpListenerInterface listener, HttpServer::AbstractHttpRequestHandler handler, Socket s, hash< auto > cx, hash< auto > hdr, auto body) destructor()
creates the object with the given attributes
auto sendImpl()
callback method for sending chunked data; this calls RestHandler::AbstractRestStreamRequestHandler::s...
hash< RestRequestServerInfo > parseRequest(string method, string path, *data http_body, reference< hash< auto > > headers)
the RestHandler namespace contains all the objects in the RestHandler module
Definition: RestHandler.qm.dox.h:475