Qore HttpServer Module Reference  0.3.12
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 (C) 2012 - 2017 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 // need mime definitions
26 
27 
28 
239 
246 namespace HttpServer {
248 
254  string get_exception_string(hash ex);
255 
256 };
257 
258 // class containing handler info
259 class HttpServer::HandlerInfo {
260 
261 public:
262  public :
263  string name;
265  string path;
266  bool isregex;
267  // content type hash
268  hash ch;
269  *list shdr;
270 
271 public:
272 
273  constructor(string n_name, HttpServer::AbstractHttpRequestHandler n_obj, string n_path, bool n_isregex = True, *softlist n_content, *softlist n_shdr);
274 
275 
276  bool matchContentType(string ct);
277 
278 
280  int matchRequest(hash hdr, int score);
281 
282 };
283 
284 // class to implement handler-handling (private)
285 class HttpServer::HttpHandlerList {
286 
287 public:
288  public :
289  hash handlers;
290  TreeMap treeMap();
291 
292 public:
293 
294  /*
295  private static checkSpecialHeaders(reference sh) {
296  foreach auto h in (\sh) {
297  if (h.typeCode() != NT_STRING)
298  throw "SETHANDLER-ERROR", sprintf("entry %d in the special header list is not a string; type: %s", $#, h.type());
299  # make sure header is in lower case for matching
300  h = tolower(h);
301  }
302  }
303  */
304 
306  setHandler(string name, string path, bool isregex = True, *softlist content, HttpServer::AbstractHttpRequestHandler obj, *softlist special_headers);
307 
308 
309  // matches a handler to the request
310  *HandlerInfo findHandler(hash hdr, reference<int> score, bool finalv = False, *reference<string> root_path);
311 
312 
313  bool empty();
314 
315 
316  int size();
317 
318 };
319 
320 // class containing dynamic handler info
321 class HttpServer::DynamicHandlerInfo : public HttpServer::HandlerInfo {
322 
323 public:
324  public :
325  Counter counter();
326 
327 public:
328 
329  constructor(string name, HttpServer::AbstractHttpRequestHandler obj, string path, bool isregex = True, *softlist content, *softlist shdr) ;
330 
331 };
332 
333 // maintains the request count for dynamic handlers (private)
334 class HttpServer::DynamicHandlerHelper {
335 
336 public:
337 private:
338 
339 public:
340 
341  private :
342  Counter c;
343 
344 public:
345 
346  constructor(Counter n_c);
347 
348 
349  destructor();
350 
351 };
352 
353 // for dynamic handler-handling (private)
354 class HttpServer::DynamicHttpHandlerList : public HttpServer::HttpHandlerList {
355 
356 public:
357  private :
358  RWLock dhl();
359 
360 public:
361 
363  setHandler(string name, string path, bool isregex, *softlist content_type, HttpServer::AbstractHttpRequestHandler obj, *softlist special_headers);
364 
365 
367  removeHandler(string name);
368 
369 
370  *DynamicHandlerInfo findHandler(hash hdr, reference<int> score, reference<DynamicHandlerHelper> dhh, *reference<string> root_path);
371 
372 };
373 
376 
377 public:
378  public :
382  const ReadTimeout = HttpServer::ReadTimeout; // recvs timeout after 30 seconds
384  const PollTimeout = 5000; // check for exit every 5 seconds while waiting
385 
386  // logging options
389 
391  const AIFlags = AI_PASSIVE | AI_ADDRCONFIG;
392 
394  const HttpMethods = (
395  "HEAD": True,
396  "POST": True,
397  "PUT": True,
398  "DELETE": True,
399  "GET": True,
400  "OPTIONS": True,
401  "PATCH": True,
402  //"TRACE": True,
403  //"CONNECT": True,
404  );
405 
408 
410  const ContentEncodings = (
411  "gzip": "gzip",
412  "deflate": "deflate",
413  "bzip2": "bzip2",
414  "x-gzip": "gzip",
415  "x-deflate": "deflate",
416  "x-bzip2": "bzip2",
417  );
418 
420  const DefaultIdleThreads = 10;
421 
423  const CompressionThreshold = 1024;
424 
434  const LLO_RECV_HEADERS = (1 << 0);
436 
438  const LLO_RECV_BODY = (1 << 1);
439 
441  const LLO_SEND_HEADERS = (1 << 2);
442 
444  const LLO_SEND_BODY = (1 << 3);
446 
447 public:
448 
450  private :
451  *code logfunc;
452  *code errlogfunc;
453 
454  // for masking HTTP request log msgs
455  *code maskfunc;
456 
457  // quit server flag
458  bool exit = False;
459 
460  // if True then verbose exception info will be logged
461  bool debug;
462 
463  Sequence seqSessions();
464  Sequence seqListeners();
465 
466  bool stopped = False;
467 
468  // permanent handlers; these handlers are never removed
469  HttpHandlerList handlers();
470 
471  // default handler
472  hash defaultHandler;
473 
474  // hash of listeners keyed by listener ID
475  hash listeners;
476 
477  // map of bind addresses to listener IDs
478  hash smap;
479 
480  // map of listener names to listener IDs
481  hash nmap;
482 
483  // listener Gate
484  Gate lm();
485 
486  // running listener counter
487  Counter c();
488 
489  // dynamic handlers
490  DynamicHttpHandlerList dhandlers();
491 
492  // connection thread pool
493  ThreadPool threadPool(-1, DefaultIdleThreads);
494 
495  // other misc response headers
496  hash hdr;
497 
498  // 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
499  *string override_encoding;
500 
501  string http_server_string;
502 
503 public:
505 
507 
515  constructor(*code n_logfunc, *code n_errlogfunc, bool n_dbg = False, string n_name = HttpServer::HttpServerString, hash n_hdr = ("X-Powered-By": "Qore/" + Qore::VersionString));
516 
517 
519  destructor();
520 
521 
523  static string getHttpServerVersionString();
524 
525  setDefaultTextEncoding(string enc);
526 
527 
528  string getDefaultTextEncoding();
529 
530 
532 
561  final list addListenersWithHandler(string hname, HttpServer::AbstractHttpRequestHandler handler, hash lp, *code logger, *code errorlogger, *code stopc, *string name, int family = AF_UNSPEC);
562 
563 
565 
589  final list addListeners(string bind, hash lp, *code logger, *code errorlogger, *code stopc, *string name, int family = AF_UNSPEC);
590 
591 
593 
609  hash addListener(softstring sock, *string cert_path, *string key_path, *string name, int family = AF_UNSPEC, *string pwd);
610 
611 
613 
629  softlist addListeners(softstring sock, *string cert_path, *string key_path, *string name, int family = AF_UNSPEC, *string pwd);
630 
631 
633 
648  list addINETListeners(*string node, softstring service, *string cert_path, *string key_path, *string name, int family = AF_UNSPEC, *string pwd);
649 
650 
652  copy();
653 
654 
656 
658  hash getListeners();
659 
660 
662 
679  hash getListenerInfo(softint id);
680 
681 
683 
700  hash getListenerInfoName(string name);
701 
702 
704  int getListenerCount();
705 
706 
708 
710  stopNoWait();
711 
712 
714  waitStop();
715 
716 
718 
723  listenerStarted(int id, hash sinfo);
724 
725 
726  // only called from the listeners - do not call externally
727  listenerStopped(HttpListener l);
728 
729 
731 
733  stop();
734 
735 
737  stopListener(softstring bind);
738 
739 
741  stopListenerID(softint id);
742 
743 
745  int getListenerTID(softint id);
746 
747 
749  setDefaultHandler(string name, HttpServer::AbstractHttpRequestHandler obj);
750 
751 
753  setHandler(string name, string path, *softlist content_type, HttpServer::AbstractHttpRequestHandler obj, *softlist special_headers, bool isregex = True);
754 
755 
757  setDynamicHandler(string name, string path, *softlist content_type, HttpServer::AbstractHttpRequestHandler obj, *softlist special_headers, bool isregex = True);
758 
759 
761  setHandler(string name, HttpServer::AbstractUrlHandler obj);
762 
763 
765  setDynamicHandler(string name, HttpServer::AbstractUrlHandler obj);
766 
767 
769  addHandlerToListener(softstring bind, string name, string path, *softlist content_type, HttpServer::AbstractHttpRequestHandler obj, *softlist special_headers, bool isregex = True);
770 
771 
773  addHandlerToListenerID(softint id, string name, string path, *softlist content_type, HttpServer::AbstractHttpRequestHandler obj, *softlist special_headers, bool isregex = True);
774 
775 
777  addHandlerToListener(softstring bind, string name, HttpServer::AbstractUrlHandler obj);
778 
779 
781  addHandlerToListenerID(softint id, string name, HttpServer::AbstractUrlHandler obj);
782 
783 
785 
795  setListenerLogOptions(softstring bind, softint code);
796 
797 
799 
809  setListenerLogOptionsID(softint id, softint code);
810 
811 
813 
816  int getListenerLogOptions(softstring bind);
817 
818 
820 
823  int getListenerLogOptionsID(softint id);
824 
825 
827  removeDynamicHandler(string name);
828 
829 
831  log(string fmt);
832 
833 
835  logError(string fmt);
836 
837 
839  sendHttpError(HttpListener listener, hash cx, Socket s, int code, string msg, *hash extra_hdrs, *string encoding);
840 
841 
843 
847  string maskData(string msg);
848 
849 
851 
862  setMaskCode(code maskfunc);
863 
864 
866 
871  static string getURLFromBind(softstring bind, *string host);
872 
874  setDebug(bool dbg = True);
875 
876 
878  bool getDebug();
879 
880 
881  startConnection(code c);
882 
883 
885 
888 private:
889  int getListenerIdFromBindUnlocked(string bind);
890 public:
891 
892 
894 
895 private:
896  setListenerLogOptionsUnlocked(softstring id, int code);
897 public:
898 
899 
901 
902 private:
903  int getListenerLogOptionsUnlocked(softstring id);
904 public:
905 
906 
908  static nothing setReplyHeaders(Socket s, hash cx, reference<hash> rv);
909 
911  // don't reimplement this method; fix/enhance it in the module
912 
913 private:
914  final HttpListener addListenerIntern(*string node, *softstring service, *Qore::SSLCertificate cert, *Qore::SSLPrivateKey key, *hash hi, *code logger, *code errorlogger, *code stopc, *string name, int family = AF_UNSPEC);
915 public:
916 
917 
918  // don't reimplement this method; fix/enhance it in the module
919 
920 private:
921  static final hash getSSLObjects(string cert_path, *string key_path, *string pwd);
922 public:
923 
924 
925  // don't reimplement this method; fix/enhance it in the module
926 
927 private:
928  final list addINETListenersIntern(*string node, softstring service, *hash sd, *hash lp, *code logger, *code errorlogger, *code stopc, *string name, int family = AF_UNSPEC);
929 public:
930 
931 
932  // don't reimplement this method; fix/enhance it in the module
933 
934 private:
935  final hash<HttpResponseInfo> noHandlerError(hash cx, hash hdr, auto body);
936 public:
937 
938 
939  // handles an incoming request - do not call externally; this method is called by the listeners when a request is received
940  // don't reimplement this method; fix/enhance it in the module
941  final handleRequest(HttpListener listener, Socket s, reference<hash> cx, hash hdr, hash hh, *data body, bool head = False, HttpPersistentHandlerInfo phi);
942 
943 
944  // sends a reply to a request
945  // don't reimplement this method; fix/enhance it in the module
946  final sendReply(HttpListener listener, Socket s, HttpServer::AbstractHttpRequestHandler handler, hash rv, reference<hash> cx, hash hdr, bool head);
947 
949 };
950 
951 class HttpServer::HttpPersistentHandlerInfo {
952 
953 public:
954  public :
955  *DynamicHandlerHelper dhh;
957 
958 public:
959 
960  destructor();
961 
962 
963  assign(*DynamicHandlerHelper n_dhh, HttpServer::AbstractHttpRequestHandler n_handler);
964 
965 
966  clear();
967 
968 };
969 
971 
974 
975 public:
976  private :
977  HttpServer serv;
978  Sequence ss;
979  *SSLCertificate cert;
980  *SSLPrivateKey key;
981  bool ssl = False;
982  auto socket;
983  hash socket_info;
984 
985  // connection counter
986  Counter cThreads();
987  bool exit = False;
988  bool stopped = False;
989  int id;
990 
991  // socket handler hash
992  hash shh;
993 
994  // mutex
995  Mutex m();
996 
997  // code references to external logging functions
998  *code logger;
999  *code errorlogger;
1000 
1001  // stop notification closure
1002  *code stopc;
1003 
1004  string name;
1005 
1006  // log recv headers flag
1007  bool log_recv_headers = False;
1008 
1009  // log recv body flag
1010  bool log_recv_body = False;
1011 
1012  // log send headers flag
1013  bool log_send_headers = False;
1014 
1015  // log send body flag
1016  bool log_send_body = False;
1017 
1018  const PollInterval = 1s;
1019  const ListenQueue = 100;
1020  const BodyLogLimit = 40;
1021 
1022 public:
1023 
1024  public :
1025  // TID of the background listener thread
1026  int tid;
1027 
1028  // listener-specific handlers
1029  HttpHandlerList handlers();
1030 
1031  // default handler info
1032  *HandlerInfo defaultHandler;
1033 
1034 public:
1035 
1036  // params: server, id, session ID sequence object, socket, rbac obj, [cert, key]
1037  constructor(HttpServer n_server, int n_id, Sequence n_ss, *string n_node, *softstring n_service, *Qore::SSLCertificate n_cert, *Qore::SSLPrivateKey n_key, *hash n_hi, *code n_logger, *code n_errorlogger, *code n_stopc, string n_name, int n_family = AF_UNSPEC);
1038 
1039 
1040  addHandlers(hash hi);
1041 
1042 
1043  setDefaultHandler(string name);
1044 
1045 
1046  copy();
1047 
1048 
1049  destructor();
1050 
1051 
1052  logRecvHeaders(softbool flag = True);
1053 
1054 
1055  logRecvBody(softbool flag = True);
1056 
1057 
1058  logSendHeaders(softbool flag = True);
1059 
1060 
1061  logSendBody(softbool flag = True);
1062 
1063 
1064  hash getLogOptions();
1065 
1066 
1067  string getName();
1068 
1069 
1070  auto getAddress();
1071 
1072 
1073  int getID();
1074 
1075 
1076  bool isSecure();
1077 
1078 
1079  hash getInfo();
1080 
1081 
1082  auto removeUserThreadContext(*string k);
1083 
1084 
1085  addUserThreadContext(hash uctx);
1086 
1087 
1088  stopNoWait();
1089 
1090 
1091  stop();
1092 
1093 
1094  logResponse(hash cx, int code, *data body, *hash hdr);
1095 
1096 
1097  logResponse(hash cx, hash rv);
1098 
1099 
1100  log(string fmt);
1101 
1102 
1103  logError(string fmt);
1104 
1105 
1106 
1107 private:
1108  mainThread();
1109 public:
1110 
1111 
1112  // thread for handling communication per connection
1113 
1114 private:
1115  connectionThread(Socket s);
1116 public:
1117 
1118 
1119  bool registerDedicatedSocket(softstring id, HttpServer::AbstractHttpSocketHandler h);
1120 
1121 
1122  removeDedicatedSocket(softstring id, HttpServer::AbstractHttpSocketHandler h);
1123 
1124 };
const AF_UNSPEC
const ReadTimeout
string get_exception_string(hash ex)
returns a multi-line string from the exception hash argument suitable for logging or output on the co...
const HttpCodes
const LP_LOGPARAMS
const ReadTimeout
default read timeout in ms
Definition: HttpServer.qm.dox.h:382
const True
const False
list list(...)
const HttpServerVersion
nothing exit(softint rc=0)
const LP_LEVELMASK
const HttpServerString
The HttpServer class implements a multithreaded HTTP server.
Definition: HttpServer.qm.dox.h:375
the main namespace for the HttpServer module
this class implements the listeners for the HttpServer class
Definition: HttpServer.qm.dox.h:973
const VersionString
hash hash(object obj)
const AI_ADDRCONFIG
const HttpCodes
map of HTTP result codes and text messages
Definition: HttpServer.qm.dox.h:407
const AI_PASSIVE