Qore HttpServerUtil Module Reference  0.3.12.1
HttpServerUtil.qm.dox.h
1 // -*- mode: c++; indent-tabs-mode: nil -*-
2 // @file HttpServerUtil.qm HTTP server base code
3 
4 /* HttpServerUtil.qm Copyright (C) 2014 - 2018 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 
86 
91 namespace HttpServer {
93  const HttpServerVersion = "0.3.11.1";
94 
96  const HttpServerString = sprintf("Qore-HTTP-Server/%s", HttpServerVersion);
97 
99  const DefaultTimeout = 30s; // recvs timeout after 30 seconds
100 
103 
105  const HttpCodes = (
106  // 100s: Informational
107  "100": "Continue",
108  "101": "Switching Protocols",
109 
110  // RFC 2518: WebDAV
111  "102": "Processing",
112 
113  // 200s: Success
114  "200": "OK",
115  "201": "Created",
116  "202": "Accepted",
117  "203": "Non-Authoritative Information",
118  "204": "No Content",
119  "205": "Reset Content",
120  "206": "Partial Content",
121 
122  // 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
123  "207": "Multi-Status",
124 
125  // 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
126  "208": "Already Reported",
127 
128  // RFC 3229
129  "226": "IM Used",
130 
131  // 300s: Redirection
132  "300": "Multiple Choices",
133  "301": "Moved Permanently",
134  "302": "Found",
135  "303": "See Other",
136  "304": "Not Modified",
137  "305": "Use Proxy",
138  //"306": "(Reserved)",
139  "307": "Temporary Redirect",
140 
141  // 400s: Client Errors
142  "400": "Bad Request",
143  "401": "Unauthorized",
144  "402": "Payment Required",
145  "403": "Forbidden",
146  "404": "Not Found",
147  "405": "Method Not Allowed",
148  "406": "Not Acceptable",
149  "407": "Proxy Authentication Required",
150  "408": "Request Timeout",
151  "409": "Conflict",
152  "410": "Gone",
153  "411": "Length Required",
154  "412": "Precondition Failed",
155  "413": "Request Entity Too Large",
156  "414": "Request-URI Too Long",
157  "415": "Unsupported Media Type",
158  "416": "Requested Range Not Satisfiable",
159  "417": "Expectation Failed",
160 
161  // RFC 2324: http://tools.ietf.org/html/rfc2324
162  "418": "I'm a teapot",
163 
164  // Returned by the Twitter Search and Trends API when the client is being rate limited
165  "420": "Enhance Yextern Calm",
166 
167  // RFC 4918: WebDAV: The request was well-formed but was unable to be followed due to semantic errors
168  "422": "Unprocessable Entity",
169 
170  // RFC 4918: WebDAV: The resource that is being accessed is locked
171  "423": "Locked",
172 
173  // RFC 4918: WebDAV: The request failed due to failure of a previous request (e.g. a PROPPATCH)
174  "424": "Failed Dependency",
175 
176  // Internet draft: Defined in drafts of "WebDAV Advanced Collections Protocol", but not present in "Web Distributed Authoring and Versioning (WebDAV) Ordered Collections Protocol"
177  "425": "Unordered Collection",
178 
179  // RFC 2817: The client should switch to a different protocol such as TLS/1.0
180  "426": "Upgrade Required",
181 
182  // 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."
183  "428": "Precondition Required",
184 
185  // RFC 6585: The user has sent too many requests in a given amount of time. Intended for use with rate limiting schemes
186  "429": "Too Many Requests",
187 
188  // RFC 6585
189  "431": "Request Header Fields Too Large",
190 
191  // 500s: Server Errors
192  "500": "Internal Server Error",
193  "501": "Not Implemented",
194  "502": "Bad Gateway",
195  "503": "Service Unavailable",
196  "504": "Gateway Timeout",
197  "505": "HTTP Version Not Supported",
198  "509": "Bandwidth Limit Exceeded",
199 
200  // RFC 2774: Further extensions to the request are required for the server to fulfill it
201  "510": "Not Extended",
202 
203  // 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)
204  "511": "Network Authentication Required",
205  );
206 
210  const LP_LOGPARAMS = 1 << 16;
212 
216 
218  public struct HttpResponseInfo {
220  int code;
221 
223  *data body;
224 
226  softbool close = False;
227 
230 
233 
235  string log;
236 
238  string errlog;
239  };
240 
242  public struct HttpHandlerResponseInfo {
244  int code;
245 
247  auto body;
248 
250  softbool close = False;
251 
254 
257 
259  string log;
260 
262  string errlog;
263  };
264 
266 
269  string http_get_url_from_bind(softstring bind, *string host);
270 
271 
273 
283  hash<Util::UriQueryInfo> parse_uri_query(string path);
284 
285 
287  nothing http_set_reply_headers(Socket s, hash cx, reference rv, *string server_string);
288 
289 
291 
304  string http_mask_data(string msg);
305 
306 };
307 
310 
311 public:
313 
315  abstract log(string fmt);
316 
318 
320  abstract logError(string fmt);
321 
323 
325  logArgs(*softlist args);
326 
327 
329 
331  logErrorArgs(*softlist args);
332 
333 };
334 
337 
338 public:
340 
342  abstract addUserThreadContext(hash uctx);
343 
345 
347  abstract auto removeUserThreadContext(*string k);
348 };
349 
351 
354 
355 public:
357 
359  bool requiresAuthentication();
360 
361 
363 
365  string getRealm();
366 
367 
369 
375  authenticate(string user, string pass = "");
376 
377 
379 
385  authenticateByIP(string ip, reference<string> user);
386 
387 
388 
389 private:
390  hash getAuthHeader();
391 public:
392 
393 
395 
396 private:
397  hash<HttpResponseInfo> do401(string msg = "Authentication is required to access this server");
398 public:
399 
400 
402 
420  *hash<HttpResponseInfo> authenticateRequest(HttpListenerInterface listener, hash hdr, reference<hash> cx);
421 
422 };
423 
426 
427 public:
429 
444  *hash<HttpResponseInfo> authenticateRequest(HttpListenerInterface listener, hash hdr, reference<hash> cx);
445 
446 };
447 
449 
458 
459 public:
460 private:
461 
462 public:
463 
464  private :
470  Socket s;
476  auto body;
479 
480 public:
481 
483 
493  constructor(HttpListenerInterface n_listener, AbstractHttpRequestHandler n_handler, Socket n_s, hash n_cx, hash n_hdr, auto n_body);
494 
495 
497  hash<HttpHandlerResponseInfo> handleRequest();
498 
499 
501 
507 private:
508  hash<HttpHandlerResponseInfo> sendResponse();
509 public:
510 
511 
513 
523 private:
524  hash<HttpHandlerResponseInfo> getResponseHeaderMessage();
525 public:
526 
527 
529 
532 private:
533  nothing recv(hash v);
534 public:
535 
536 
538 
539 private:
540  auto send();
541 public:
542 
543 
545 
555 private:
556  logChunk(bool send, int size);
557 public:
558 
559 
561 
573 private:
574  hash<HttpResponseInfo> getResponseHeaderMessageImpl();
575 public:
576 
577 
579 
589 private:
590  nothing recvImpl(hash v);
591 public:
592 
593 
595 
599 private:
600  auto sendImpl();
601 public:
602 
603 };
604 
606 
614 
615 public:
616  public :
619 
621  bool decompress = True;
622 
625 
627  bool stream;
628 
631 
633  const NotificationThreadKey = "_AHRH_pc";
634 
636  const PersistenceThreadKey = "_AHRH_p";
637 
638 public:
639 
641 
644  constructor(*AbstractAuthenticator n_auth, softbool n_stream = False);
645 
646 
648  bool isPersistent();
649 
650 
652  setPersistent(bool p = True);
653 
654 
656  notifyClosed(*code c);
657 
658 
660 
664  string maskData(string msg);
665 
666 
668  static staticNotificationCleanup();
669 
671  static staticPersistenceCleanup();
672 
674  nothing persistentClosed();
675 
676 
678 
679 private:
680  nothing checkPersistent(hash cx, hash hdr);
681 public:
682 
683 
685 
710  hash<HttpResponseInfo> handleRequest(hash cx, hash hdr, *data body);
711 
712 
714  hash<HttpResponseInfo> handleRequest(HttpListenerInterface listener, Socket s, hash cx, hash hdr, *data body);
715 
716 
718 
719 private:
720  AbstractStreamRequest getStreamRequestImpl(HttpListenerInterface listener, Socket s, hash cx, hash hdr, *data body);
721 public:
722 
723 
725  static data decodeBody(string ce, binary body, *string enc);
726 
728  static binary encodeBody(string ce, data body);
729 
731  *data getMessageBody(Socket s, hash hdr, *data body, bool decode = True);
732 
733 
735 
751  static *string getLogMessage(hash cx, hash api, reference params, *reference<string> args);
752 
754 
757 
758 
760 
763 
764 
766  static hash<HttpResponseInfo> makeResponse(int code, string fmt);
767 
769  static hash<HttpResponseInfo> makeResponse(hash hdr, int code, string fmt);
770 
772  static hash<HttpResponseInfo> makeResponse(int code, *data body, *hash hdr);
773 
775  static hash<HttpResponseInfo> make400(string fmt);
776 
778  static hash<HttpResponseInfo> make400(hash hdr, string fmt);
779 
781  static hash<HttpResponseInfo> make501(string fmt);
782 
784  static hash<HttpResponseInfo> make501(hash hdr, string fmt);
785 
787  static hash<HttpResponseInfo> redirect(hash cx, hash hdr, string path);
788 };
789 
792 
793 public:
794  public :
796  string url_root;
797 
798 public:
799 
801 
804  constructor(string n_url_root, *AbstractAuthenticator auth) ;
805 
806 
808  string getRelativePath(string path);
809 
810 };
811 
813 
816 
817 public:
818  private :
820  bool stop = False;
821 
824 
827 
829  Mutex m();
830 
831 public:
832 
834 
837 
838 
840 
856  start(softstring lid, hash cx, hash hdr, Socket s);
857 
858 
860 
864  stop(softstring lid);
865 
866 
868 
870  stop();
871 
872 
874 
902  abstract hash handleRequest(hash cx, hash hdr, *data b);
903 
905 
922 private:
923  abstract startImpl(softstring lid, hash cx, hash hdr, Socket s);
924 public:
925 
927 
930 private:
931  stopImpl(string lid);
932 public:
933 
934 
936 
937 private:
938  stopImpl();
939 public:
940 
941 };
softbool close
set this key to True if the connection should be unconditionally closed when the handler returns ...
Definition: HttpServerUtil.qm.dox.h:226
static hash< HttpResponseInfo > redirect(hash cx, hash hdr, string path)
generates a redirect hash for the given path
static hash< HttpResponseInfo > make400(string fmt)
creates a hash for an HTTP 400 error response with the response message body as a string ...
bool reply_sent
this key can be set to True if the reply has already been sent (by a chunked callback for example) ...
Definition: HttpServerUtil.qm.dox.h:232
string sprintf(string fmt,...)
softbool close
set this key to True if the connection should be unconditionally closed when the handler returns ...
Definition: HttpServerUtil.qm.dox.h:250
logErrorArgs(*softlist args)
calls logError() with the given args
hash< HttpResponseInfo > do401(string msg="Authentication is required to access this server")
returns a 401 repsonse with the given string argument as the message body
authenticateByIP(string ip, reference< string > user)
called when the connection requires authentication, but no authentication credentials were supplied...
hash hdr
a hash of request headers
Definition: HttpServerUtil.qm.dox.h:474
const ReadTimeout
read timeout in ms
Definition: HttpServerUtil.qm.dox.h:102
const HttpCodes
map of HTTP result codes and text messages
Definition: HttpServerUtil.qm.dox.h:105
abstract class for streaming HTTP chunked requests/responses
Definition: HttpServerUtil.qm.dox.h:457
abstract hash handleRequest(hash cx, hash hdr, *data b)
called by the HTTP server to handle incoming HTTP requests
const LP_LOGPARAMS
bit for logging argument
Definition: HttpServerUtil.qm.dox.h:211
string getRealm()
returns the authentication realm as a string
abstract class that all HTTP request handler objects must inherit from
Definition: HttpServerUtil.qm.dox.h:613
class providing automatic authentication for all requests
Definition: HttpServerUtil.qm.dox.h:425
*AbstractAuthenticator auth
the optional AbstractAuthenticator for requests to this handler
Definition: HttpServerUtil.qm.dox.h:618
*hash< HttpResponseInfo > authenticateRequest(HttpListenerInterface listener, hash hdr, reference< hash > cx)
primary method called to authenticate each request
abstract log(string fmt)
called to log information to the registered log code
hash lh
hash of listener references; this is to stop all connections associated with a particular listener ...
Definition: HttpServerUtil.qm.dox.h:823
*hash hdr
set this key to a hash of extra header information to be returned with the response ...
Definition: HttpServerUtil.qm.dox.h:229
string maskData(string msg)
this method can be used to mask data in debug messages
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...
this abstract class defines the public interface of the private HttpListener class defined in the Htt...
Definition: HttpServerUtil.qm.dox.h:336
string http_mask_data(string msg)
this function can be used to mask data in log messages
AbstractStreamRequest getStreamRequestImpl(HttpListenerInterface listener, Socket s, hash cx, hash hdr, *data body)
returns the AbstractStreamRequest object for handling chunked requests
*data getMessageBody(Socket s, hash hdr, *data body, bool decode=True)
optionally retrieves and post-processes any message body
AbstractHttpRequestHandler handler
the request handler for the request
Definition: HttpServerUtil.qm.dox.h:468
string errlog
a string can be returned here which will be logged in the HTTP server&#39;s error log file (if any) ...
Definition: HttpServerUtil.qm.dox.h:238
bool decompress
if POSTed data should be decompressed automatically if there is content-encoding
Definition: HttpServerUtil.qm.dox.h:621
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...
binary binary()
bool stream
if the handler supports streaming requests/responses with chunked data
Definition: HttpServerUtil.qm.dox.h:627
constructor(string n_url_root, *AbstractAuthenticator auth)
creates the object based on the URL root and optional authenticator
string errlog
a string can be returned here which will be logged in the HTTP server&#39;s error log file (if any) ...
Definition: HttpServerUtil.qm.dox.h:262
Mutex m()
listener reference hash mutex
static hash< HttpResponseInfo > makeResponse(int code, string fmt)
creates a hash for an HTTP response with the response code and the response message body as a formatt...
const False
bool requiresAuthentication()
called to check if the connection requires authentication
notifyClosed(*code c)
calls the argument when the persistent connection is closed
string http_get_url_from_bind(softstring bind, *string host)
returns a complete URL from a bind address
abstract base class for external authentication
Definition: HttpServerUtil.qm.dox.h:353
static staticNotificationCleanup()
removes the thread-local data key in case the object is destroyed in another thread ...
hash< HttpHandlerResponseInfo > sendResponse()
called to either create the response hash or send a chunked response directly
stopImpl()
called from the HTTP server when the socket should be closed due to an external request; the start() ...
restoreThreadLocalData(*hash data)
called after handleRequest() with any data returned from saveThreadData()
timeout timeout_ms
send and receive timeout
Definition: HttpServerUtil.qm.dox.h:478
stop()
called from the HTTP server when the socket should be closed due to an external request; the start() ...
*hash< HttpResponseInfo > authenticateRequest(HttpListenerInterface listener, hash hdr, reference< hash > cx)
primary method called to authenticate each request
nothing checkPersistent(hash cx, hash hdr)
this method will throw an exception if a persistent connection cannot be granted
hash cx
the call context variable
Definition: HttpServerUtil.qm.dox.h:472
Socket s
the Socket object for the response
Definition: HttpServerUtil.qm.dox.h:470
constructor(HttpListenerInterface n_listener, AbstractHttpRequestHandler n_handler, Socket n_s, hash n_cx, hash n_hdr, auto n_body)
creates the object with the given attributes
abstract auto removeUserThreadContext(*string k)
removes the given key from the "uctx" context key; if no argument is provided, then the "uctx" contex...
const HttpServerVersion
version of the HttpServer&#39;s implementation
Definition: HttpServerUtil.qm.dox.h:93
static staticPersistenceCleanup()
removes the thread-local data key in case the object is destroyed in another thread ...
*data body
the message body to return in the response; if this key is returned, then the reply is sent immediate...
Definition: HttpServerUtil.qm.dox.h:223
constructor(*AbstractAuthenticator auth)
create the object optionally with the given AbstractAuthenticator
nothing recv(hash v)
this is the primary callback for receiving chunked data; data will be logged, and then recvImpl() is ...
*hash hdr
set this key to a hash of extra header information to be returned with the response ...
Definition: HttpServerUtil.qm.dox.h:253
hash< HttpHandlerResponseInfo > getResponseHeaderMessage()
this method returns the response message description hash by calling getResponseHeaderMessageImpl() ...
HttpListenerInterface listener
an HttpListenerInterface object for the listener serving the request for logging purposes ...
Definition: HttpServerUtil.qm.dox.h:466
hash< HttpHandlerResponseInfo > handleRequest()
handles the request
static binary encodeBody(string ce, data body)
encodes a message body with content-encoding
nothing recvImpl(hash v)
callback method for receiving chunked data; the default implementation in this base class does nothin...
bool reply_sent
this key can be set to True if the reply has already been sent (by a chunked callback for example) ...
Definition: HttpServerUtil.qm.dox.h:256
this abstract class defines the interface for classes that provide logging methods ...
Definition: HttpServerUtil.qm.dox.h:309
abstract addUserThreadContext(hash uctx)
adds user-defined data to be returned in the "uctx" context key when serving requests from this liste...
auto body
any message body given in a non-chunked request; could already be deserialized
Definition: HttpServerUtil.qm.dox.h:476
int code
the HTTP return code (see HttpServer::HttpCodes for possible values)
Definition: HttpServerUtil.qm.dox.h:244
const DefaultTimeout
default timeout in ms
Definition: HttpServerUtil.qm.dox.h:99
string log
a string can be returned here which will be logged in the HTTP server&#39;s log file (if any) ...
Definition: HttpServerUtil.qm.dox.h:259
int code
the HTTP return code (see HttpServer::HttpCodes for possible values)
Definition: HttpServerUtil.qm.dox.h:220
abstract class that all HTTP dedicated socket handler objects must inherit from
Definition: HttpServerUtil.qm.dox.h:815
abstract class for HTTP request handlers anchored at a specific URL
Definition: HttpServerUtil.qm.dox.h:791
the return value of HTTP handler methods with potentially unserialized message bodies ...
Definition: HttpServerUtil.qm.dox.h:242
static data decodeBody(string ce, binary body, *string enc)
decodes a message body with content-encoding
hash< Util::UriQueryInfo > 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...
const LP_LEVELMASK
mask for the log level
Definition: HttpServerUtil.qm.dox.h:214
constructor(*AbstractAuthenticator n_auth, softbool n_stream=False)
create the object optionally with the given AbstractAuthenticator
const HttpServerString
default HTTP server string
Definition: HttpServerUtil.qm.dox.h:96
timeout timeout_ms
send and receive socket timeout in milliseconds
Definition: HttpServerUtil.qm.dox.h:630
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: HttpServerUtil.qm.dox.h:624
authenticate(string user, string pass="")
called to authenticate a user for a connection
the main namespace for the HttpServer and HttpServerUtil modules
Definition: HttpServerUtil.qm.dox.h:91
logChunk(bool send, int size)
this method can be overridden in base classes to log each HTTP chunk sent
auto send()
this is the primary callback for sending chunked responses; first sendImpl() is called to get the raw...
setPersistent(bool p=True)
called externally to notify the handler that the connection will be persistent
const NotificationThreadKey
thread-local key string for notification callbacks
Definition: HttpServerUtil.qm.dox.h:633
the return value of HTTP handler methods where any message body has been serialized for sending over ...
Definition: HttpServerUtil.qm.dox.h:218
abstract logError(string fmt)
called to log error information to the registered error log code
*hash saveThreadLocalData()
called before handleRequest() any data returned here will be given to restoreThreadLocalData() after ...
logArgs(*softlist args)
calls log() with the given args
nothing http_set_reply_headers(Socket s, hash cx, reference rv, *string server_string)
helper function for setting HTTP response headers
hash hash(object obj)
string url_root
root part of URL for matching requests
Definition: HttpServerUtil.qm.dox.h:796
auto body
the message body to return in the response; for higher-level handlers this can be any data type that ...
Definition: HttpServerUtil.qm.dox.h:247
nothing persistentClosed()
called externally when a persistent connection is closed
static hash< HttpResponseInfo > make501(string fmt)
creates a hash for an HTTP 501 error response with the response message body as a string ...
const PersistenceThreadKey
thread-local key string for the persistent flag
Definition: HttpServerUtil.qm.dox.h:636
static *string getLogMessage(hash cx, hash api, reference params, *reference< string > args)
helper method for handling log messages
hash< HttpResponseInfo > getResponseHeaderMessageImpl()
this method should return the response message description hash
hash lsh
hash of listener stop flags
Definition: HttpServerUtil.qm.dox.h:826
hash< HttpResponseInfo > handleRequest(hash cx, hash hdr, *data body)
will be called when a request is received that should be directed to the handler
bool isPersistent()
returns True if the current connection is persistent, False if not
string log
a string can be returned here which will be logged in the HTTP server&#39;s log file (if any) ...
Definition: HttpServerUtil.qm.dox.h:235
auto sendImpl()
callback method for sending chunked data; the default implementation in this base class does nothing ...