Qore HttpServer Module Reference  0.3.7
 All Classes Namespaces Functions Variables Groups Pages
HttpServer.qm.dox.h
1 // -*- mode: c++; indent-tabs-mode: nil -*-
2 // @file HttpServer.qm HTTP multi-threaded server module definition
3 
4 /* HttpServer.qm Copyright 2012 - 2013 David Nichols
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 // need mime definitions
26 
27 
28 /* Version History
29  * 2013-03-05 v0.3.7: David Nichols <david@qore.org>
30  + fixed a bug in parsing arguments in parse_uri_query()
31  + updated parse_uri_query() to accept both "&" and ";" as argument separators
32  + added support for the PUT and DELETE methods and for optional message bodies independent of the HTTP method
33  + fixed handler matching to use a score for each handler and to check dynamic handlers also for a match if the fixed handlers don't provide a perfect match
34  + fixed response handling to not overwrite the \c Connection header if present from the handler
35  + fixed response handling to only return error reponses with codes >= 400
36  + implemented theAbstractHttpSocketHandler handler class to support dedicated socket connections when switching protocols in handlers
37  + do not add HTML to the msg body from explicit error responses from handlers
38  + improved HTTP server log messages
39  + added "family" argument to HttpServer::add*Listener*() methods
40  + turned of TCP_NODELAY by default and use socket shutdown when closing sockets instead
41  + set the listen backlog queue size to 100 by default (previously was hardcoded internally in Qore to 5)
42  + use the new ThreadPool class introduced in Qore 0.8.8 to pre-allocate threads to reduce latency for new socket connections
43  + improved handler matching algorithm
44  + implemented many performance improvements
45  + implemented support for simple string path matching when finding a handler for a request
46  + added static AbstractHttpRequestHandler::redirect() to help in generating 301 Moved Permanently messages
47 
48  * 2012-12-18 v0.3.6: David Nichols <david@qore.org>
49  + fixed a race condition in tracking active requests in dynamic HTTP handlers and removing dynamic HTTP handlers
50 
51  * 2012-09-20 v0.3.5: David Nichols <david@qore.org>
52  + fixed bugs in regexes in the HttpServer::addListeners() and HttpServer::addListenersWithHandler() methods
53  + updated module example code in summary
54  + added "listener-id" to request context hash
55 
56  * 2012-06-01 v0.3.4: David Nichols <david@qore.org>
57  + added public parse_uri_query() function
58 
59  * 2012-05-24 v0.3.3: David Nichols <david@qore.org>
60  + updated to a user module
61  + added support for custom redirects from user handlers
62  + use the Mime module for mime definitions
63 
64  * v0.3.2: David Nichols <david@qore.org>
65  + added support for listeners with specific handler lists
66  + added the ability to manage dynamic content handlers
67  + implemented content-encoding handling flags in AbstractHttpRequestHandler
68  + implemented support for "identity" encoding (if anyone ever sends it)
69 
70  * v0.3.1: David Nichols <david@qore.org>
71  + added ipv6 support in qore 0.8.2
72 
73  * v0.3.0: David Nichols <david@qore.org>
74  + added the ability to start and stop listeners on demand
75 
76  * v0.2.9: David Nichols <david@qore.org>
77  + updates for new SSL and timeout behavior with with Socket class with qore 0.8.1+
78  + set socket encoding to UTF-8 by default
79  + add "charset=utf-8" to Content-Type header if not already present
80  + add "text/html" to Content-Type header if no content-type is given by the handler
81  + fixed setting X.509 certificate and private key for HTTPS listeners
82  + require qore >= 0.8.1 for new Socket features
83 
84  * v0.2.8: David Nichols <david@qore.org>
85  + converted to hard typing for use with %require-types
86  + require qore >= 0.8.0 for new Socket features
87 
88  * v0.2.7: David Nichols <david@qore.org>
89  + set TCP_NODELAY on all sockets to ensure that clients get all data before closing the socket, especially in case of errors
90  + require qore >= 0.7.4 for new Socket features
91 
92  * v0.2.6: David Nichols <david@qore.org>
93  + minor fixes for SOAP support
94  + improved handler matching
95 
96  * v0.2.5: David Nichols <david@qore.org>
97  + minor fixes for SOAP support
98 
99  * v0.2.4: David Nichols <david@qore.org>
100  + improved Content-Type handling
101  + improved URL/path support
102 
103  * v0.2.3: David Nichols <david@qore.org>
104  + bzip2 content-encoding support
105 
106  * v0.2.2: David Nichols <david@qore.org>
107  + basic authentication
108 
109  * v0.2.1: David Nichols <david@qore.org>
110  + implementing logic to handle "deflate" and "gzip" content-encoding
111  + chunked content-encoding supported for POSTs
112  + Date: header always sent as per HTTP 1.1 spec
113 
114  * v0.2.0: David Nichols <david@qore.org>
115  + modular/multiple listener support added
116  + https support added
117 
118  note that this server suffers from the following limitations, among many others:
119  + not totally HTTP 1.1 compliant although claims to be
120 */
121 
290 
297 namespace HttpServer {
299 
305  hash parse_uri_query(string path);
306 
307 
309 
315  string get_exception_string(hash ex);
316 
317 };
318 
319 // class containing handler info
320 class HttpServer::HandlerInfo {
321 
322 public:
323  public :
324  string name;
325  AbstractHttpRequestHandler obj;
326  string path;
327  bool isregex;
328  // content type hash
329  hash ch;
330  *list shdr;
331 
332 public:
333 
334  constructor(string name, AbstractHttpRequestHandler obj, string path, bool isregex = True, *softlist content, *softlist shdr);
335 
336 
337  bool matchContentType(string ct);
338 
339 
341  int matchRequest(hash hdr, int score);
342 
343 };
344 
345 // class to implement handler-handling (private)
346 class HttpServer::HttpHandlerList {
347 
348 public:
349  public :
350  hash handlers;
351 
352 public:
353 
354 
355 private:
356  static checkSpecialHeaders(reference sh);
357 public:
358 
359 
361  setHandler(string name, string path, bool isregex = True, *softlist content, AbstractHttpRequestHandler obj, *softlist special_headers);
362 
363 
364  // matches a handler to the request
365  *HandlerInfo findHandler(hash hdr, reference score, bool final = False);
366 
367 
368  bool empty();
369 
370 
371  int size();
372 
373 };
374 
375 // class containing dynamic handler info
376 class HttpServer::DynamicHandlerInfo : public HttpServer::HandlerInfo {
377 
378 public:
379  public :
380  Counter counter();
381 
382 public:
383 
384  constructor(string name, AbstractHttpRequestHandler obj, string path, bool isregex = True, *softlist content, *softlist shdr);
385 
386 };
387 
388 // maintains the request count for dynamic handlers (private)
389 class HttpServer::DynamicHandlerHelper {
390 
391 public:
392 private:
393 
394 public:
395 
396  private :
397  Counter c;
398 
399 public:
400 
401  constructor(Counter c);
402 
403 
404  destructor();
405 
406 };
407 
408 // for dynamic handler-handling (private)
409 class HttpServer::DynamicHttpHandlerList : public HttpServer::HttpHandlerList {
410 
411 public:
412  private :
413  RWLock dhl();
414 
415 public:
416 
418  setHandler(string name, string path, bool isregex, *softlist content_type, AbstractHttpRequestHandler obj, *softlist special_headers);
419 
420 
422  removeHandler(string name);
423 
424 
425  *DynamicHandlerInfo findHandler(hash hdr, reference score, reference dhh);
426 
427 };
428 
430 
433 
434 public:
436 
438  bool requiresAuthentication();
439 
440 
442 
444  string getRealm();
445 
446 
448 
454  authenticate(string user, string pass = "");
455 
456 
458 
464  authenticateByIP(string ip, reference user);
465 
466 
467 
468 private:
469  hash getAuthHeader();
470 public:
471 
472 
473  private hash do401(string msg = "Authentication is required to access this server");
474 
475 
477 
486  *hash authenticateRequest(HttpListener listener, hash hdr, reference cx);
487 
488 };
489 
491 
494 
495 public:
496  public :
499 
501  bool decompress = True;
502 
505 
506 public:
507 
509 
512 
513 
515 
538  hash handleRequest(hash cx, hash hdr, *data body);
539 
540 
542 
549  static *string getLogMessage(hash cx, hash api, reference params, *reference args);
550 
552 
555 
556 
558 
561 
562 
564  static hash makeResponse(int code, string fmt);
565 
567  static hash makeResponse(hash hdr, int code, string fmt);
568 
570  static hash makeResponse(int code, *data body, *hash hdr);
571 
573  static hash make400(string fmt);
574 
576  static hash make400(hash hdr, string fmt);
577 
579  static hash make501(string fmt);
580 
582  static hash make501(hash hdr, string fmt);
583 
585  static hash redirect(hash cx, hash hdr, string path);
586 };
587 
590 
591 public:
592  public :
594  string url_root;
595 
596 public:
597 
599 
603 
604 
606  string getRelativePath(string path);
607 
608 };
609 
611 
614 
615 public:
616  private :
618  bool stop = False;
619 
622 
625 
627  Mutex m();
628 
629 public:
630 
632 
635 
636 
638 
652  start(softstring lid, hash cx, hash hdr, Socket s);
653 
654 
656 
660  stop(softstring lid);
661 
662 
664 
666  stop();
667 
668 
670 
696  abstract hash handleRequest(hash cx, hash hdr, *data b);
697 
699 
714 private:
715  abstract startImpl(softstring lid, hash cx, hash hdr, Socket s);
716 public:
717 
719 
722 private:
723  stopImpl(string lid);
724 public:
725 
726 
728 
729 private:
730  stopImpl();
731 public:
732 
733 };
734 
737 
738 public:
739  public :
741  const Version = "0.3.7";
743  const ReadTimeout = 30000; // recvs timeout after 30 seconds
745  const PollTimeout = 5000; // check for exit every 5 seconds while waiting
746 
747  // logging options
748  const LP_LOGPARAMS = 1 << 16;
749  const LP_LEVELMASK = LP_LOGPARAMS - 1;
750 
753 
755  const HttpMethods = (
756  "HEAD": True,
757  "POST": True,
758  "PUT": True,
759  "DELETE": True,
760  "GET": True,
761  //"TRACE": True,
762  //"CONNECT": True,
763  );
764 
766  const HttpCodes = (
767  // 100s: Informational
768  "100": "Continue",
769  "101": "Switching Protocols",
770 
771  // RFC 2518: WebDAV
772  "102": "Processing",
773 
774  // 200s: Success
775  "200": "OK",
776  "201": "Created",
777  "202": "Accepted",
778  "203": "Non-Authoritative Information",
779  "204": "No Content",
780  "205": "Reset Content",
781  "206": "Partial Content",
782 
783  // RFC 4918: WebDAV: The message body that follows is an XML message and can contain a number of separate response codes, depending on how many sub-requests were made
784  "207": "Multi-Status",
785 
786  // RFC 5842: WebDAV: The members of a DAV binding have already been enumerated in a previous reply to this request, and are not being included again
787  "208": "Already Reported",
788 
789  // RFC 3229
790  "226": "IM Used",
791 
792  // 300s: Redirection
793  "300": "Multiple Choices",
794  "301": "Moved Permanently",
795  "302": "Found",
796  "303": "See Other",
797  "304": "Not Modified",
798  "305": "Use Proxy",
799  //"306": "(Reserved)",
800  "307": "Temporary Redirect",
801 
802  // 400s: Client Errors
803  "400": "Bad Request",
804  "401": "Unauthorized",
805  "402": "Payment Required",
806  "403": "Forbidden",
807  "404": "Not Found",
808  "405": "Method Not Allowed",
809  "406": "Not Acceptable",
810  "407": "Proxy Authentication Required",
811  "408": "Request Timeout",
812  "409": "Conflict",
813  "410": "Gone",
814  "411": "Length Required",
815  "412": "Precondition Failed",
816  "413": "Request Entity Too Large",
817  "414": "Request-URI Too Long",
818  "415": "Unsupported Media Type",
819  "416": "Requested Range Not Satisfiable",
820  "417": "Expectation Failed",
821 
822  // RFC 2324: http://tools.ietf.org/html/rfc2324
823  "418": "I'm a teapot",
824 
825  // Returned by the Twitter Search and Trends API when the client is being rate limited
826  "420": "Enhance Yextern Calm",
827 
828  // RFC 4918: WebDAV: The request was well-formed but was unable to be followed due to semantic errors
829  "422": "Unprocessable Entity",
830 
831  // RFC 4918: WebDAV: The resource that is being accessed is locked
832  "423": "Locked",
833 
834  // RFC 4918: WebDAV: The request failed due to failure of a previous request (e.g. a PROPPATCH)
835  "424": "Failed Dependency",
836 
837  // Internet draft: Defined in drafts of "WebDAV Advanced Collections Protocol", but not present in "Web Distributed Authoring and Versioning (WebDAV) Ordered Collections Protocol"
838  "425": "Unordered Collection",
839 
840  // RFC 2817: The client should switch to a different protocol such as TLS/1.0
841  "426": "Upgrade Required",
842 
843  // RFC 6585: The origin server requires the request to be conditional. Intended to prevent "the 'lost update' problem, where a client GETs a resource's state, modifies it, and PUTs it back to the server, when meanwhile a third party has modified the state on the server, leading to a conflict."
844  "428": "Precondition Required",
845 
846  // RFC 6585: The user has sent too many requests in a given amount of time. Intended for use with rate limiting schemes
847  "429": "Too Many Requests",
848 
849  // RFC 6585
850  "431": "Request Header Fields Too Large",
851 
852  // 500s: Server Errors
853  "500": "Internal Server Error",
854  "501": "Not Implemented",
855  "502": "Bad Gateway",
856  "503": "Service Unavailable",
857  "504": "Gateway Timeout",
858  "505": "HTTP Version Not Supported",
859  "509": "Bandwidth Limit Exceeded",
860 
861  // RFC 2774: Further extensions to the request are required for the server to fulfill it
862  "510": "Not Extended",
863 
864  // RFC 6585: The client needs to authenticate to gain network access. Intended for use by intercepting proxies used to control access to the network (e.g. "captive portals" used to require agreement to Terms of Service before granting full Internet access via a Wi-Fi hotspot)
865  "511": "Network Authentication Required",
866  );
867 
870  "gzip": "gzip",
871  "deflate": "deflate",
872  "bzip2": "bzip2",
873  "x-gzip": "gzip",
874  "x-deflate": "deflate",
875  "x-bzip2": "bzip2",
876  );
877 
879  const DefaultIdleThreads = 10;
880 
881 public:
882 
884  private :
885  *code logfunc;
886  *code errlogfunc;
887 
888  // quit server flag
889  bool exit = False;
890 
891  // if True then verbose exception info will be logged
892  bool debug;
893 
894  Sequence seqSessions();
895  Sequence seqListeners();
896 
897  string httpserverstring;
898 
899  bool stopped = False;
900 
901  // permanent handlers; these handlers are never removed
902  HttpHandlerList handlers();
903 
904  // default handler
905  hash defaultHandler;
906 
907  // hash of listeners keyed by listener ID
908  hash listeners;
909 
910  // map of bind addresses to listener IDs
911  hash smap;
912 
913  // map of listener names to listener IDs
914  hash nmap;
915 
916  // listener Gate
917  Gate lm();
918 
919  // running listener counter
920  Counter c();
921 
922  // dynamic handlers
923  DynamicHttpHandlerList dhandlers();
924 
925  // connection thread pool
926  ThreadPool threadPool(-1, DefaultIdleThreads);
927 
928  // other misc response headers
929  hash hdr;
930 
931  // override message body encoding if none is received from the sender; http://tools.ietf.org/html/rfc2616#section-3.7.1 states that it must be iso-8850-1
932  *string override_encoding;
933 
934 public:
936 
938 
946  constructor(*code logfunc, *code errlogfunc, bool dbg = False, string name = sprintf("Qore-HTTP-Server/%s", HttpServer::Version), hash hdr = ("X-Powered-By": "Qore/" + Qore::VersionString));
947 
948 
950  destructor();
951 
952 
953  setDefaultTextEncoding(string enc);
954 
955 
956  string getDefaultTextEncoding();
957 
958 
960 
988  final list addListenersWithHandler(string hname, AbstractHttpRequestHandler handler, hash lp, *code logger, *code errorlogger, *code stopc, *string name, int family = AF_UNSPEC);
989 
990 
992 
1007  hash addListener(softstring sock, *string cert_path, *string key_path, *string name, int family = AF_UNSPEC);
1008 
1009 
1011 
1026  softlist addListeners(softstring sock, *string cert_path, *string key_path, *string name, int family = AF_UNSPEC);
1027 
1028 
1030 
1044  list addINETListeners(*string node, softstring service, *string cert_path, *string key_path, *string name, int family = AF_UNSPEC);
1045 
1046 
1048  copy();
1049 
1050 
1052 
1054  hash getListeners();
1055 
1056 
1058 
1075  hash getListenerInfo(softint id);
1076 
1077 
1079 
1096  hash getListenerInfoName(string name);
1097 
1098 
1100  int getListenerCount();
1101 
1102 
1104 
1106  stopNoWait();
1107 
1108 
1110  waitStop();
1111 
1112 
1113  // only called from the listeners - do not call externally
1114  listenerStopped(HttpListener l);
1115 
1116 
1118 
1120  stop();
1121 
1122 
1124  stopListener(softstring bind);
1125 
1126 
1128  stopListenerID(softint id);
1129 
1130 
1132  int getListenerTID(softint id);
1133 
1134 
1137 
1138 
1140  setHandler(string name, string path, *softlist content_type, AbstractHttpRequestHandler obj, *softlist special_headers, bool isregex = True);
1141 
1142 
1144  setDynamicHandler(string name, string path, *softlist content_type, AbstractHttpRequestHandler obj, *softlist special_headers, bool isregex = True);
1145 
1146 
1148  setHandler(string name, AbstractUrlHandler obj);
1149 
1150 
1152  setDynamicHandler(string name, AbstractUrlHandler obj);
1153 
1154 
1156  addHandlerToListener(softstring bind, string name, string path, *softlist content_type, AbstractHttpRequestHandler obj, *softlist special_headers, bool isregex = True);
1157 
1158 
1160  addHandlerToListenerID(softint id, string name, string path, *softlist content_type, AbstractHttpRequestHandler obj, *softlist special_headers, bool isregex = True);
1161 
1162 
1164  addHandlerToListener(softstring bind, string name, AbstractUrlHandler obj);
1165 
1166 
1168  addHandlerToListenerID(softint id, string name, AbstractUrlHandler obj);
1169 
1170 
1172  removeDynamicHandler(string name);
1173 
1174 
1176  log();
1177 
1178 
1180  logError();
1181 
1182 
1184  logArgs(softlist args = ());
1185 
1186 
1188  logErrorArgs(softlist args = ());
1189 
1190 
1192  sendHttpError(HttpListener listener, hash cx, Socket s, int code, string msg, *hash extra_hdrs, *string encoding);
1193 
1194 
1196 
1198  static string getURLFromBind(softstring bind, *string host);
1199 
1201  setDebug(bool dbg = True);
1202 
1203 
1205  bool getDebug();
1206 
1207 
1208  startConnection(code c);
1209 
1210 
1212  // don't reimplement this method; fix/enhance it in the module
1213 
1214 private:
1215  final HttpListener addListenerIntern(*string node, *softstring service, *SSLCertificate cert, *SSLPrivateKey key, *hash hi, *code logger, *code errorlogger, *code stopc, *string name, int family = AF_UNSPEC);
1216 public:
1217 
1218 
1219  // don't reimplement this method; fix/enhance it in the module
1220 
1221 private:
1222  static final hash getSSLObjects(string cert_path, *string key_path);
1223 public:
1224 
1225 
1226  // don't reimplement this method; fix/enhance it in the module
1227 
1228 private:
1229  final list addINETListenersIntern(*string node, softstring service, *hash sd, *hash lp, *code logger, *code errorlogger, *code stopc, *string name, int family = AF_UNSPEC);
1230 public:
1231 
1232 
1233  // don't reimplement this method; fix/enhance it in the module
1234 
1235 private:
1236  final hash noHandlerError(hash cx, hash hdr, any body);
1237 public:
1238 
1239 
1240  // handles an incoming request - do not call externally; this method is called by the listeners when a request is received
1241  // don't reimplement this method; fix/enhance it in the module
1242  final handleRequest(HttpListener listener, Socket s, reference cx, hash hdr, hash hh, *data body, bool head = False);
1243 
1245 };
1246 
1249 
1250 public:
1251  private :
1252  HttpServer serv;
1253  Sequence ss;
1254  *SSLCertificate cert;
1255  *SSLPrivateKey key;
1256  bool ssl = False;
1257  any socket;
1258  hash socket_info;
1259 
1260  // connection counter
1261  Counter cThreads();
1262  bool exit = False;
1263  bool stopped = False;
1264  int id;
1265 
1266  // socket handler hash
1267  hash shh;
1268 
1269  // mutex
1270  Mutex m();
1271 
1272  // code references to external logging functions
1273  *code logger;
1274  *code errorlogger;
1275 
1276  // stop notification closure
1277  *code stopc;
1278 
1279  string name;
1280 
1281  const PollInterval = 1s;
1282  const ListenQueue = 100;
1283 
1284 public:
1285 
1286  public :
1287  // TID of the background listener thread
1288  int tid;
1289 
1290  // listener-specific handlers
1291  HttpHandlerList handlers();
1292 
1293  // default handler info
1294  *HandlerInfo defaultHandler;
1295 
1296 public:
1297 
1298  // params: server, id, session ID sequence object, socket, rbac obj, [cert, key]
1299  constructor(HttpServer server, int id, Sequence ss, *string node, *softstring service, *SSLCertificate cert, *SSLPrivateKey key, *hash hi, *code logger, *code errorlogger, *code stopc, string name, int family = AF_UNSPEC);
1300 
1301 
1302  addHandlers(hash hi);
1303 
1304 
1305  setDefaultHandler(string name);
1306 
1307 
1308  copy();
1309 
1310 
1311  destructor();
1312 
1313 
1314  string getName();
1315 
1316 
1317  any getAddress();
1318 
1319 
1320  int getID();
1321 
1322 
1323  bool isSecure();
1324 
1325 
1326  hash getInfo();
1327 
1328 
1329  stopNoWait();
1330 
1331 
1332  stop();
1333 
1334 
1335  logResponse(hash cx, int code, *data body, *hash hdr);
1336 
1337 
1338  logResponse(hash cx, hash rv);
1339 
1340 
1341  log();
1342 
1343 
1344  logError();
1345 
1346 
1347 
1348 private:
1349  mainThread();
1350 public:
1351 
1352 
1353  // thread for handling communication per connection
1354 
1355 private:
1356  connectionThread(Socket s);
1357 public:
1358 
1359 
1360  bool registerDedicatedSocket(softstring id, AbstractHttpSocketHandler h);
1361 
1362 
1363  removeDedicatedSocket(softstring id, AbstractHttpSocketHandler h);
1364 
1365 };
logError()
called to log error information to the registered error log code
logErrorArgs(softlist args=())
calls the error log function/closure with the given args
logArgs(softlist args=())
calls the log function/closure with the given args
const AF_UNSPEC
string sprintf(string fmt,...)
hash getListeners()
returns a hash of listener information
hash addListener(softstring sock, *string cert_path, *string key_path, *string name, int family=AF_UNSPEC)
adds a global listener to the server
string get_exception_string(hash ex)
returns a multi-line string from the exception hash argument suitable for logging or output on the co...
abstract hash handleRequest(hash cx, hash hdr, *data b)
called by the HTTP server to handle incoming HTTP requests
setDebug(bool dbg=True)
turns on or off debugging; when debugging is enabled more verbose error messages are reported ...
string getRealm()
returns the authentication realm as a string
abstract class that all HTTP request handler objects must inherit from
Definition: HttpServer.qm.dox.h:493
*AbstractAuthenticator auth
the optional AbstractAuthenticator for requests to this handler
Definition: HttpServer.qm.dox.h:498
static string getURLFromBind(softstring bind, *string host)
returns a complete URL from a bind address
const ReadTimeout
default read timeout in ms
Definition: HttpServer.qm.dox.h:743
removeDynamicHandler(string name)
remove dynamic handler
hash lh
hash of listener references; this is to stop all connections associated with a particular listener ...
Definition: HttpServer.qm.dox.h:621
constructor(*AbstractAuthenticator auth)
create the object optionally with the given AbstractAuthenticator
addHandlerToListenerID(softint id, string name, string path, *softlist content_type, AbstractHttpRequestHandler obj, *softlist special_headers, bool isregex=True)
adds a request handler to a listener given the listener&#39;s id
destructor()
calls stop() and destroys the object
addHandlerToListener(softstring bind, string name, string path, *softlist content_type, AbstractHttpRequestHandler obj, *softlist special_headers, bool isregex=True)
adds a request handler to a listener given the listener&#39;s name or bind address
const True
start(softstring lid, hash cx, hash hdr, Socket s)
called from the HTTP server after the handleRequest() method indicates that a dedicated connection sh...
string getRelativePath(string path)
returns the relative path anchored from the url_root if possible; URI query arguments are stripped of...
setDynamicHandler(string name, string path, *softlist content_type, AbstractHttpRequestHandler obj, *softlist special_headers, bool isregex=True)
sets a dynamic request handler according to the arguments given
const DefaultIdleThreads
default number of idle threads to have waiting for new connections (accross all listeners) ...
Definition: HttpServer.qm.dox.h:879
stopListener(softstring bind)
stops a single listener based on its name or bind address; does not return until all connections on t...
stopListenerID(softint id)
stops a single listener based on its listener ID; does not return until all connections on the listen...
const HttpMethods
supported HTTP methods
Definition: HttpServer.qm.dox.h:755
bool decompress
if POSTed data should be decompressed automatically if there is content-encoding
Definition: HttpServer.qm.dox.h:501
abstract startImpl(softstring lid, hash cx, hash hdr, Socket s)
called from the HTTP server after the handleRequest() method indicates that a dedicated connection sh...
stop()
stops all listeners; only returns when all connections are closed on all listeners ...
constructor(string url_root, *AbstractAuthenticator auth)
creates the object based on the URL root and optional authenticator
Mutex m()
listener reference hash mutex
static hash make501(string fmt)
creates a hash for an HTTP 501 error response with the response message body as a string ...
constructor(*code logfunc, *code errlogfunc, bool dbg=False, string name=sprintf("Qore-HTTP-Server/%s", HttpServer::Version), hash hdr=("X-Powered-By":"Qore/"+Qore::VersionString))
creates the HttpServer
const False
bool requiresAuthentication()
called to check if the connection requires authentication
list list(...)
abstract base class for external authentication
Definition: HttpServer.qm.dox.h:432
static hash makeResponse(int code, string fmt)
creates a hash for an HTTP response with the response code and the response message body as a formatt...
static hash make400(string fmt)
creates a hash for an HTTP 400 error response with the response message body as a string ...
stopImpl()
called from the HTTP server when the socket should be closed due to an external request; the start() ...
hash getListenerInfo(softint id)
returns a hash of information about the listener given the listener ID
restoreThreadLocalData(*hash data)
called after handleRequest() with any data returned from saveThreadData()
stop()
called from the HTTP server when the socket should be closed due to an external request; the start() ...
const PollTimeout
default poll timeout in ms
Definition: HttpServer.qm.dox.h:745
softlist addListeners(softstring sock, *string cert_path, *string key_path, *string name, int family=AF_UNSPEC)
adds one or more global listeners according to the bind address
constructor(*AbstractAuthenticator auth)
create the object optionally with the given AbstractAuthenticator
nothing exit(softint rc=0)
hash parse_uri_query(string path)
parses a URI path for a arguments and a method; where the method is the part of the path before the f...
final list addListenersWithHandler(string hname, AbstractHttpRequestHandler handler, hash lp, *code logger, *code errorlogger, *code stopc, *string name, int family=AF_UNSPEC)
adds a dedicated listener to the server with an explicit/dedicated handler for incoming connections ...
static *string getLogMessage(hash cx, hash api, reference params, *reference args)
helper method for handling log messages
sendHttpError(HttpListener listener, hash cx, Socket s, int code, string msg, *hash extra_hdrs, *string encoding)
sends an HTTP error message on the socket
stopNoWait()
stops all listeners; does not wait for all connections on the listeners to close
bool getDebug()
returns the current status of the debug flag
abstract class that all HTTP dedicated socket handler objects must inherit from
Definition: HttpServer.qm.dox.h:613
abstract class for HTTP request handlers anchored at a specific URL
Definition: HttpServer.qm.dox.h:589
waitStop()
waits for all listeners to be stopped; call after calling HttpServer::stopNoWait() ...
hash handleRequest(hash cx, hash hdr, *data body)
will be called when a request is received that should be directed to the handler
const AIFlags
address info flags
Definition: HttpServer.qm.dox.h:752
bool decompress_to_string
if automatically decompressed POSTed data should be converted to a string (if False, then it will be decompressed to a binary)
Definition: HttpServer.qm.dox.h:504
copy()
throws an exception; these objects do not support copying
const Version
version of the HttpServer&#39;s implementation
Definition: HttpServer.qm.dox.h:741
setDefaultHandler(string name, AbstractHttpRequestHandler obj)
sets the default request handler when no other handler can be matched
The HttpServer class implements a multithreaded HTTP server primarily designed for serving RPC-style ...
Definition: HttpServer.qm.dox.h:736
authenticate(string user, string pass="")
called to authenticate a user for a connection
setHandler(string name, string path, *softlist content_type, AbstractHttpRequestHandler obj, *softlist special_headers, bool isregex=True)
sets a request handler according to the arguments given
int getListenerCount()
returns the number of running HTTP listeners
this class implements the listeners for the HttpServer class
Definition: HttpServer.qm.dox.h:1248
log()
called to log information to the registered log code
const VersionString
*hash saveThreadLocalData()
called before handleRequest() any data returned here will be given to restoreThreadLocalData() after ...
list addINETListeners(*string node, softstring service, *string cert_path, *string key_path, *string name, int family=AF_UNSPEC)
adds one or more global listeners according to the bind address
authenticateByIP(string ip, reference user)
called when the connection requires authentication, but no authentication credentials were supplied...
hash hash(object obj)
string url_root
root part of URL for matching requests
Definition: HttpServer.qm.dox.h:594
const AI_ADDRCONFIG
hash getListenerInfoName(string name)
returns a hash of information about the listener given the listener name or bind ID ...
const HttpCodes
map of HTTP result codes and text messages
Definition: HttpServer.qm.dox.h:766
const AI_PASSIVE
static hash redirect(hash cx, hash hdr, string path)
generates a redirect hash for the given path
*hash authenticateRequest(HttpListener listener, hash hdr, reference cx)
primary method called to authenticate each request
hash lsh
hash of listener stop flags
Definition: HttpServer.qm.dox.h:624
const ContentEncodings
content-encodings supported; this is a hash to simulate a set with O(ln(n)) access times ...
Definition: HttpServer.qm.dox.h:869
int getListenerTID(softint id)
gets the TID of a listener based on its listener ID