Qore RestHandler Module Reference 1.6.1
Loading...
Searching...
No Matches
RestHandler.qm.dox.h
1// -*- mode: c++; indent-tabs-mode: nil -*-
3
4/* RestHandler.qm Copyright (C) 2013 - 2022 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
471namespace RestHandler {
473
481
482public:
483
484
485protected:
487 hash<auto> cx;
488
490 *hash<auto> ex;
491
493 *hash<auto> ah;
494
496 hash<auto> rhdr;
497
500
501public:
502
504
518 constructor(hash<auto> n_cx, *hash<auto> n_ah);
519
520
522
531 hash<HttpServer::HttpHandlerResponseInfo> getResponseHeaderMessage();
532
533
535
545 nothing recv(hash<auto> v);
546
547
549
552 auto send();
553
554
557
558
561
562
564 setTimeout(timeout n_timeout_ms);
565
566
569
570
572 streamError(hash<auto> n_ex);
573
574
576
585 abstract hash<auto> getResponseHeaderMessageImpl();
586
588
598 abstract nothing recvImpl(hash<auto> v);
599
601
604 abstract auto sendImpl();
605 };
606
609
610public:
611protected:
613 bool deserialized;
614
615public:
616
620 hash<auto> cx, hash<auto> hdr, auto body)
622 cx + (exists body ? {'deserialized': True} : NOTHING), hdr, body);
623
624
627
628
629 // callback method for the response header; this calls @ref RestHandler::AbstractRestStreamRequestHandler::getResponseHeaderMessage() and returns the result
639protected:
640 hash<HttpServer::HttpHandlerResponseInfo> getResponseHeaderMessageImpl();
641public:
642
643
645
655protected:
656 nothing recvImpl(hash<auto> v);
657public:
658
659
661
664protected:
665 auto sendImpl();
666public:
667
668 };
669
672
673public:
675 hash<string, AbstractRestClass> class_hash;
676
678 const RestBasicMethodSet = map {$1: True}, RestHandler::Methods.iterator();
679
680 constructor();
681
682
684 abstract string name();
685
688
689
691
716 *AbstractRestClass subClass(string name, hash<auto> cx, *hash<auto> args);
717
718
720
743 *AbstractRestClass subClassImpl(string name, hash<auto> cx, *hash<auto> args);
744
745
747 hash<HttpServer::HttpHandlerResponseInfo> handleRequest(HttpListenerInterface listener, RestHandler rh,
748 Socket s, *list<string> cl, string mn, hash<auto> cx, *hash<auto> args) {
749 if (!args && cx.body.typeCode() == NT_HASH);
750
751 if (cl);
752
753
754 // try to mask passwords and sensitive data in args
755 string astr = rh.maskData(sprintf("%y", args));
756 rh.logDebug("REST DBG: class %y: dispatching method %y args: %s", name(), mn, astr);
757 return dispatchStream(listener, rh, s, mn, args, cx);
758 }
759
761 private hash<HttpServer::HttpHandlerResponseInfo> dispatchStream(HttpListenerInterface listener,
762 RestHandler rh, Socket s, string mn, *hash<auto> ah, hash<auto> cx) {
763 string sn = "stream" + mn[0].upr() + mn.substr(1);
765 try {
766 cx.socketobject = s;
767 rsh = call_object_method_args(self, sn, (cx, ah));
768 } catch (hash<ExceptionInfo> ex) {
769 if (ex.err == "METHOD-DOES-NOT-EXIST" && ex.desc.find(sn) != -1) {
770 if (cx.hdr."transfer-encoding" == "chunked")
771 cx.body = rh.getMessageBody(s, cx.hdr, NOTHING);
772
773 return cast<hash<HttpHandlerResponseInfo>>(dispatch(rh, mn, ah, cx));
774 }
775 string desc = !cx.debug
776 ? sprintf("%s: %s: %s", get_ex_pos(ex), ex.err, ex.desc)
777 : get_exception_string(ex);
778 rh.logDebug("REST DBG: class %y: stream method %y: %s", name(), sn, desc);
779 rethrow;
780 }
781 try {
782 RestStreamRequest req(rsh, listener, rh, s, cx, cx.hdr, cx.hdr."content-length" ? cx.body : NOTHING);
783 return req.handleRequest();
784 } catch (hash<ExceptionInfo> ex) {
785 // make sure the error is registered with the stream handler
786 if (rsh) {
787 # issue #4291: handle errors here correctly
788 try {
789 rsh.streamError(ex);
790 } catch (hash<ExceptionInfo> ex1) {
791 rh.logError("cannot register error %s: %s with stream handler: %s: %s", ex.err, ex.desc,
792 ex1.err, ex1.desc);
793 }
794 }
795 string desc = !cx.debug
796 ? sprintf("%s: %s: %s", get_ex_pos(ex), ex.err, ex.desc)
797 : get_exception_string(ex);
798 rh.logDebug("REST DBG: class %y: stream method %y: %s", name(), sn, desc);
799 rethrow;
800 }
801 }
802
804
825 private hash<HttpServer::HttpHandlerResponseInfo> dispatch(RestHandler rh, string mn, *hash<auto> ah,
826 hash<auto> cx) {
827 try {
828 return cast<hash<HttpHandlerResponseInfo>>(call_object_method_args(self, mn, (cx, ah)));
829 } catch (hash<ExceptionInfo> ex) {
830 if (ex.err == "METHOD-DOES-NOT-EXIST") {
831 // try to mask passwords in args
832 string astr = rh.maskData(sprintf("%y", ah));
833 rh.logError("DISPATCH-ERROR: cannot dispatch to unimplemented method %y: class %y, args: %s", mn,
834 name(), astr);
835 # see if alternate methods would work
836 list hl = ();
837 # break flag
838 bool brk;
839 foreach hash<auto> mh in (RestHandler::Methods.pairIterator()) {
840 string nmn = mh.value + cx.rest_method;
841 if (self.hasCallableMethod(nmn)) {
842 if (mh.key == cx.hdr.method) {
843 brk = True;
844 break;
845 }
846 hl += mh.key;
847 }
848 }
849 if (!brk) {
850 if (!hl)
851 return cast<hash<HttpHandlerResponseInfo>>(RestHandler::make501("REST class %y (%s) does "
852 "not implement method %y", name(), self.className(),
853 cx.orig_method ? cx.orig_method : mn));
854
855 string ml = foldl $1 + "," + $2, hl;
856 string desc = sprintf("HTTP method %s is unimplemented in REST class %y (%s)", cx.hdr.method,
857 name(), self.className());
858 if (cx.orig_method)
859 desc += sprintf(" REST method %y", cx.orig_method);
860 desc += sprintf(", available methods: %s", ml);
861 return cast<hash<HttpHandlerResponseInfo>>(
863 );
864 }
865 }
866 string desc = !cx.debug
867 ? sprintf("%s: %s: %s", get_ex_pos(ex), ex.err, ex.desc)
868 : get_exception_string(ex);
869 rh.logDebug("REST DBG: class %y: method %y: %s", name(), mn, desc);
870 rethrow;
871 }
872 }
873
875
888protected:
889 hash<HttpServer::HttpHandlerResponseInfo> unknownSubClassError(string cls_name, hash<auto> cx, *hash<auto> ah);
890public:
891
892
894
906protected:
907 *hash<string, bool> doGetPossibleSubClasses(hash<auto> cx, *hash<auto> ah);
908public:
909
910 };
911
913
924
925public:
927 const Err501 = new hash<HttpResponseInfo>({
928 "code": 501,
929 "body": "not implemented",
930 });
931
933 const Methods = {
934 "GET": "get",
935 "POST": "post",
936 "PUT": "put",
937 "DELETE": "del",
938 "OPTIONS": "options",
939 "PATCH": "patch",
940 };
941
942protected:
945
948
949public:
950
952
959 RestSchemaValidator::AbstractRestSchemaValidator validator = new NullRestSchemaValidator())
960 ;
961
962
964
972 RestSchemaValidator::AbstractRestSchemaValidator validator = new NullRestSchemaValidator(logger))
973 ;
974
975
977 string name();
978
979
982
983
985
1006 auto handleExternalRequest(string method, string path, *hash<auto> body, hash<auto> cx = {});
1007
1008
1010
1039 hash<HttpResponseInfo> handleRequest(HttpListenerInterface listener, Socket s, hash<auto> cx, hash<auto> hdr,
1040 *data b) {
1041 //logDebug("REST DBG: cx: %N", cx);
1042 //logDebug("REST DBG: hdr: %N", hdr);
1043
1044 auto body = b;
1045
1046 // get rest class name
1047 string path = cx.url.path ?? "";
1048
1049 removeRootPath(\path);
1050
1051 hash<RestRequestServerInfo> req;
1052 try {
1053 if (b) {
1054 string bstr = maskData(b.typeCode() == NT_STRING ? trim(b) : sprintf("%y", b));
1055 logDebug("REST DBG: body: %s", bstr);
1056 }
1057
1058 req = validator.parseRequest(hdr.method, path, body, \hdr);
1059 } catch (hash<ExceptionInfo> ex) {
1060 logDebug("REST DBG: %s", get_exception_string(ex));
1061 // return a 400 Bad Request response to encoding, serialization, or validation errors
1062 if (ex.err == "INVALID-ENCODING"
1063 || ex.err == "ENCODING-CONVERSION-ERROR"
1064 || ex.err == "DESERIALIZATION-ERROR"
1065 || ex.err == "SCHEMA-VALIDATION-ERROR")
1066 return AbstractHttpRequestHandler::makeResponse(400, sprintf("%s: %s", ex.err, ex.desc),
1067 errorResponseHeaders(cx));
1068 if (ex.err == "INVALID-METHOD") {
1069 string ml = (foldl $1 + "," + $2, ex.arg) ?? "";
1070 return AbstractHttpRequestHandler::makeResponse(405, sprintf("HTTP method %y is not supported "
1071 "with URI path %y; supported methods: %s", hdr.method, path, ml ?* "<none>"),
1072 errorResponseHeaders(cx) + {"Allow": ml});
1073 }
1074 rethrow;
1075 }
1076
1077 // get object and args
1078 hash<auto> ah = path ? (
1079 "method": req.path,
1080 "params": req.query,
1081 ) : {};
1082 //path ? parse_uri_query(path) : {};
1083
1084 *hash<auto> args;
1085 if (ah.params);
1086
1087
1088 if (exists body)
1089 body = req.body;
1090 else
1091 body = args;
1092
1093 // reflect body in arguments if body is a hash
1094 if (body.typeCode() == NT_HASH)
1095 map args.$1 = body.$1, keys body, !exists args.$1;
1096
1097 if (!Methods.(hdr.method))
1098 return AbstractHttpRequestHandler::make400("unsupported HTTP method %y given in REST call %y",
1099 hdr.method, path);
1100
1101 // make method name
1102 string mn;
1103 if (args.action);
1104 else if (body.action);
1105 else {
1106 mn = Methods.(hdr.method);
1107 }
1108
1109 cx.rest_action_method = mn;
1110
1111 // remove leading slash from method name
1112 if (ah.method ==1)
1113 splice ah.method, 0, 1;
1114
1115 // get class chain
1116 *list<string> cl;
1117 if (ah.method);
1118
1119
1120 // make a hash of "accept" values
1121 *string astr = hdr.accept;
1122 hash<auto> aih;
1123 if (astr);
1124 else {
1125 // http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html: If no Accept header field is present, then
1126 # it is assumed that the client accepts all media types
1127 aih."*/*" = True;
1128 }
1129
1130 //logDebug("REST DBG: aih: %y", aih);
1131
1132 // set up context hash
1133 cx += {"hdr": hdr, "body": body, "aih": aih};
1134
1135 // handle call with class
1136 hash<HttpHandlerResponseInfo> rv;
1137
1138 try {
1139 rv = dispatchRequest(listener, s, cl, mn, path, cx, args);
1140 } catch (hash<ExceptionInfo> ex) {
1141 string desc = !cx.debug
1142 ? sprintf("%s: %s: %s", get_ex_pos(ex), ex.err, ex.desc)
1143 : get_exception_string(ex);
1144
1145 logError(desc);
1146 rv = returnRestException(ex);
1147 }
1148
1149 if (!rv.reply_sent);
1150
1151
1152 //logDebug("REST DBG: rv: %N", rv);
1153
1154 return cast<hash<HttpResponseInfo>>(rv);
1155 }
1156
1158
1160protected:
1161 *hash<auto> errorResponseHeaders(hash<auto> cx);
1162public:
1163
1164
1166 private hash<HttpHandlerResponseInfo> dispatchRequest(HttpListenerInterface listener, Socket s,
1167 *list<string> class_list, string method_name, string path, hash<auto> cx, *hash<auto> args) {
1168 AbstractRestClass rcls;
1169
1170 // get initial class
1171 *string cls = shift class_list;
1172
1173 if (!cls);
1174 else {
1175 *AbstractRestClass c = subClass(cls, cx, args);
1176 if (!c) {
1177 // issue #2994: if we are on the last class and there is no "action" argument; see if we can f
1178 # ind an action method instead
1179 if (!class_list && !args.action) {
1180 string mname = sprintf("%s%s%s", method_name, cls[0].upr(), cls[1..]);
1181 if (self.hasCallableMethod(mname)) {
1182 rcls = self;
1183 method_name = mname;
1184 }
1185 }
1186
1187 if (!rcls) {
1188 return unknownSubClassError(cls, cx, args);
1189 }
1190 } else {
1191 rcls = c;
1192 }
1193 }
1194
1195 return rcls.handleRequest(listener, self, s, class_list, method_name, cx, args);
1196 }
1197
1199
1202protected:
1203 hash<HttpHandlerResponseInfo> returnRestException(hash<ExceptionInfo> ex);
1204public:
1205
1206
1208protected:
1209 checkExceptionSerializable(reference<hash<ExceptionInfo>> ex);
1210public:
1211
1212
1214 hash<auto> get(hash<auto> cx, *hash<auto> ah);
1215
1216
1218 removeRootPath(reference<string> path);
1219
1220
1222 requestDeserializationError(hash<auto> hdr, hash<auto> cx, string body);
1223
1224
1226 responseSerializationError(hash<auto> cx, *hash<auto> aih, hash<auto> rv);
1227
1228
1230
1232 logInfo(string fmt);
1233
1234
1236
1238 logError(string fmt);
1239
1240
1242
1244 logDebug(string fmt);
1245
1246
1248 static hash<HttpHandlerResponseInfo> make200(string fmt);
1249
1251 static hash<HttpHandlerResponseInfo> make200(hash<auto> hdr, string fmt);
1252
1254 static hash<HttpHandlerResponseInfo> make400(string fmt);
1255
1257 static hash<HttpHandlerResponseInfo> make400(hash<auto> hdr, string fmt);
1258
1260 static hash<HttpHandlerResponseInfo> makeResponse(int code, auto body, *hash<auto> hdr);
1261
1263 static hash<HttpHandlerResponseInfo> make500(string fmt);
1264
1266 static hash<HttpHandlerResponseInfo> make500(hash<auto> hdr, string fmt);
1267
1269 static hash<HttpHandlerResponseInfo> make501(string fmt);
1270
1272 static hash<HttpHandlerResponseInfo> make501(hash<auto> hdr, string fmt);
1273 };
1274};
1275
1276// private, unexported namespace
1277namespace Priv {
1278 // dumHttpListenerInterface class
1279class DummyListenerInterface : public HttpListenerInterface {
1280
1281public:
1282 addUserThreadContext(hash<auto> uctx);
1283
1284
1285 auto removeUserThreadContext(*string k);
1286
1287
1288 log(string fmt);
1289
1290
1291 logError(string fmt);
1292
1293 };
1294};
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:671
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:825
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:761
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:747
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:675
*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:678
the base abstract class for REST stream request handlers
Definition: RestHandler.qm.dox.h:480
hash< auto > rhdr
headers to add in the response
Definition: RestHandler.qm.dox.h:496
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:487
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:493
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:499
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:490
*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:933
RestSchemaValidator::AbstractRestSchemaValidator validator
REST schema validator.
Definition: RestHandler.qm.dox.h:947
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:1039
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:1166
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:944
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:608
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:471