Qore HttpServerUtil Module Reference  0.3.11
 All Classes Namespaces Functions Variables Groups Pages
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 - 2016 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 
71 
76 namespace HttpServer {
78  const HttpServerVersion = "0.3.11";
79 
81  const HttpServerString = sprintf("Qore-HTTP-Server/%s", HttpServerVersion);
82 
84  const DefaultTimeout = 30s; // recvs timeout after 30 seconds
85 
88 
90  const HttpCodes = (
91  // 100s: Informational
92  "100": "Continue",
93  "101": "Switching Protocols",
94 
95  // RFC 2518: WebDAV
96  "102": "Processing",
97 
98  // 200s: Success
99  "200": "OK",
100  "201": "Created",
101  "202": "Accepted",
102  "203": "Non-Authoritative Information",
103  "204": "No Content",
104  "205": "Reset Content",
105  "206": "Partial Content",
106 
107  // 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
108  "207": "Multi-Status",
109 
110  // 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
111  "208": "Already Reported",
112 
113  // RFC 3229
114  "226": "IM Used",
115 
116  // 300s: Redirection
117  "300": "Multiple Choices",
118  "301": "Moved Permanently",
119  "302": "Found",
120  "303": "See Other",
121  "304": "Not Modified",
122  "305": "Use Proxy",
123  //"306": "(Reserved)",
124  "307": "Temporary Redirect",
125 
126  // 400s: Client Errors
127  "400": "Bad Request",
128  "401": "Unauthorized",
129  "402": "Payment Required",
130  "403": "Forbidden",
131  "404": "Not Found",
132  "405": "Method Not Allowed",
133  "406": "Not Acceptable",
134  "407": "Proxy Authentication Required",
135  "408": "Request Timeout",
136  "409": "Conflict",
137  "410": "Gone",
138  "411": "Length Required",
139  "412": "Precondition Failed",
140  "413": "Request Entity Too Large",
141  "414": "Request-URI Too Long",
142  "415": "Unsupported Media Type",
143  "416": "Requested Range Not Satisfiable",
144  "417": "Expectation Failed",
145 
146  // RFC 2324: http://tools.ietf.org/html/rfc2324
147  "418": "I'm a teapot",
148 
149  // Returned by the Twitter Search and Trends API when the client is being rate limited
150  "420": "Enhance Yextern Calm",
151 
152  // RFC 4918: WebDAV: The request was well-formed but was unable to be followed due to semantic errors
153  "422": "Unprocessable Entity",
154 
155  // RFC 4918: WebDAV: The resource that is being accessed is locked
156  "423": "Locked",
157 
158  // RFC 4918: WebDAV: The request failed due to failure of a previous request (e.g. a PROPPATCH)
159  "424": "Failed Dependency",
160 
161  // Internet draft: Defined in drafts of "WebDAV Advanced Collections Protocol", but not present in "Web Distributed Authoring and Versioning (WebDAV) Ordered Collections Protocol"
162  "425": "Unordered Collection",
163 
164  // RFC 2817: The client should switch to a different protocol such as TLS/1.0
165  "426": "Upgrade Required",
166 
167  // 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."
168  "428": "Precondition Required",
169 
170  // RFC 6585: The user has sent too many requests in a given amount of time. Intended for use with rate limiting schemes
171  "429": "Too Many Requests",
172 
173  // RFC 6585
174  "431": "Request Header Fields Too Large",
175 
176  // 500s: Server Errors
177  "500": "Internal Server Error",
178  "501": "Not Implemented",
179  "502": "Bad Gateway",
180  "503": "Service Unavailable",
181  "504": "Gateway Timeout",
182  "505": "HTTP Version Not Supported",
183  "509": "Bandwidth Limit Exceeded",
184 
185  // RFC 2774: Further extensions to the request are required for the server to fulfill it
186  "510": "Not Extended",
187 
188  // 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)
189  "511": "Network Authentication Required",
190  );
191 
195  const LP_LOGPARAMS = 1 << 16;
197 
201 
203 
206  string http_get_url_from_bind(softstring bind, *string host);
207 
208 
210 
218  hash parse_uri_query(string path);
219 
220 
222  nothing http_set_reply_headers(Socket s, hash cx, reference rv, *string server_string);
223 
224 };
225 
228 
229 public:
231 
233  abstract log(string fmt);
234 
236 
238  abstract logError(string fmt);
239 
241 
243  logArgs(*softlist args);
244 
245 
247 
249  logErrorArgs(*softlist args);
250 
251 };
252 
255 
256 public:
258 
260  abstract addUserThreadContext(hash uctx);
261 
263 
265  abstract any removeUserThreadContext(*string k);
266 };
267 
269 
272 
273 public:
275 
277  bool requiresAuthentication();
278 
279 
281 
283  string getRealm();
284 
285 
287 
293  authenticate(string user, string pass = "");
294 
295 
297 
303  authenticateByIP(string ip, reference user);
304 
305 
306  private hash getAuthHeader();
307 
308 
309  private hash do401(string msg = "Authentication is required to access this server");
310 
311 
313 
322  *hash authenticateRequest(HttpListenerInterface listener, hash hdr, reference cx);
323 
324 };
325 
328 
329 public:
331 
337  *hash authenticateRequest(HttpListenerInterface listener, hash hdr, reference cx);
338 
339 };
340 
342 
351 
352 public:
353 private:
354 
355 public:
356 
357  private :
363  Socket s;
369  any body;
372 
373 public:
374 
376 
386  constructor(HttpListenerInterface n_listener, AbstractHttpRequestHandler n_handler, Socket n_s, hash n_cx, hash n_hdr, any n_body);
387 
388 
391 
392 
394 
399  private hash sendResponse();
400 
401 
403 
412  private hash getResponseHeaderMessage();
413 
414 
416 
418  private nothing recv(hash v);
419 
420 
422  private any send();
423 
424 
425  private logChunk(bool send, int size);
426 
427 
429 
441 
442 
444 
453  private nothing recvImpl(hash v);
454 
455 
457 
460  private any sendImpl();
461 
462 };
463 
465 
473 
474 public:
475  public :
478 
480  bool decompress = True;
481 
484 
486  bool stream;
487 
490 
492  const NotificationThreadKey = "_AHRH_pc";
493 
495  const PersistenceThreadKey = "_AHRH_p";
496 
497 public:
498 
500 
503  constructor(*AbstractAuthenticator n_auth, softbool n_stream = False);
504 
505 
507  bool isPersistent();
508 
509 
511  setPersistent(bool p = True);
512 
513 
515  notifyClosed(*code c);
516 
517 
519  static staticNotificationCleanup();
520 
522  static staticPersistenceCleanup();
523 
525  nothing persistentClosed();
526 
527 
529  private nothing checkPersistent(hash cx, hash hdr);
530 
531 
533 
557  hash handleRequest(hash cx, hash hdr, *data body);
558 
559 
561  hash handleRequest(HttpListenerInterface listener, Socket s, hash cx, hash hdr, *data body);
562 
563 
565  private AbstractStreamRequest getStreamRequestImpl(HttpListenerInterface listener, Socket s, hash cx, hash hdr, *data body);
566 
567 
569  static data decodeBody(string ce, binary body, *string enc);
570 
572  static binary encodeBody(string ce, data body);
573 
575  *data getMessageBody(Socket s, hash hdr, *data body, bool decode = True);
576 
577 
579 
586  static *string getLogMessage(hash cx, hash api, reference params, *reference args);
587 
589 
592 
593 
595 
598 
599 
601  static hash makeResponse(int code, string fmt);
602 
604  static hash makeResponse(hash hdr, int code, string fmt);
605 
607  static hash makeResponse(int code, *data body, *hash hdr);
608 
610  static hash make400(string fmt);
611 
613  static hash make400(hash hdr, string fmt);
614 
616  static hash make501(string fmt);
617 
619  static hash make501(hash hdr, string fmt);
620 
622  static hash redirect(hash cx, hash hdr, string path);
623 };
624 
627 
628 public:
629  public :
631  string url_root;
632 
633 public:
634 
636 
639  constructor(string n_url_root, *AbstractAuthenticator auth) ;
640 
641 
643  string getRelativePath(string path);
644 
645 };
646 
648 
651 
652 public:
653  private :
655  bool stop = False;
656 
659 
662 
664  Mutex m();
665 
666 public:
667 
669 
672 
673 
675 
690  start(softstring lid, hash cx, hash hdr, Socket s);
691 
692 
694 
698  stop(softstring lid);
699 
700 
702 
704  stop();
705 
706 
708 
735  abstract hash handleRequest(hash cx, hash hdr, *data b);
736 
738 
753  private abstract startImpl(softstring lid, hash cx, hash hdr, Socket s);
754 
756 
758  private stopImpl(string lid);
759 
760 
762  private stopImpl();
763 
764 };
string sprintf(string fmt,...)
logErrorArgs(*softlist args)
calls logError() with the given args
hash hdr
a hash of request headers
Definition: HttpServerUtil.qm.dox.h:367
private nothing recvImpl(hash v)
callback method for receiving chunked data; the default implementation in this base class does nothin...
const ReadTimeout
read timeout in ms
Definition: HttpServerUtil.qm.dox.h:87
const HttpCodes
map of HTTP result codes and text messages
Definition: HttpServerUtil.qm.dox.h:90
abstract class for streaming HTTP chunked requests/responses
Definition: HttpServerUtil.qm.dox.h:350
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:196
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:472
class providing automatic authentication for all requests
Definition: HttpServerUtil.qm.dox.h:327
*AbstractAuthenticator auth
the optional AbstractAuthenticator for requests to this handler
Definition: HttpServerUtil.qm.dox.h:477
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:658
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:254
*hash authenticateRequest(HttpListenerInterface listener, hash hdr, reference cx)
primary method called to authenticate each request
*data getMessageBody(Socket s, hash hdr, *data body, bool decode=True)
optionally retrieves and post-processes any message body
private hash sendResponse()
called to either create the response hash or send a chunked response directly
AbstractHttpRequestHandler handler
the request handler for the request
Definition: HttpServerUtil.qm.dox.h:361
bool decompress
if POSTed data should be decompressed automatically if there is content-encoding
Definition: HttpServerUtil.qm.dox.h:480
abstract private startImpl(softstring lid, hash cx, hash hdr, Socket s)
called from the HTTP server after the handleRequest() method indicates that a dedicated connection sh...
constructor(HttpListenerInterface n_listener, AbstractHttpRequestHandler n_handler, Socket n_s, hash n_cx, hash n_hdr, any n_body)
creates the object with the given attributes
private hash getResponseHeaderMessageImpl()
this method should return the response message description hash
binary binary()
bool stream
if the handler supports streaming requests/responses with chunked data
Definition: HttpServerUtil.qm.dox.h:486
constructor(string n_url_root, *AbstractAuthenticator auth)
creates the object based on the URL root and optional authenticator
Mutex m()
listener reference hash mutex
private stopImpl()
called from the HTTP server when the socket should be closed due to an external request; the start() ...
static hash make501(string fmt)
creates a hash for an HTTP 501 error response with the response message body as a string ...
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:271
abstract any removeUserThreadContext(*string k)
removes the given key from the &quot;uctx&quot; context key; if no argument is provided, then the &quot;uctx&quot; contex...
static staticNotificationCleanup()
removes the thread-local data key in case the object is destroyed in another thread ...
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 ...
restoreThreadLocalData(*hash data)
called after handleRequest() with any data returned from saveThreadData()
private nothing recv(hash v)
this is the primary callback for receiving chunked data; data will be logged, and then recvImpl() is ...
timeout timeout_ms
send and receive timeout
Definition: HttpServerUtil.qm.dox.h:371
stop()
called from the HTTP server when the socket should be closed due to an external request; the start() ...
hash cx
the call context variable
Definition: HttpServerUtil.qm.dox.h:365
Socket s
the Socket object for the response
Definition: HttpServerUtil.qm.dox.h:363
private any sendImpl()
callback method for sending chunked data; the default implementation in this base class does nothing ...
const HttpServerVersion
version of the HttpServer&#39;s implementation
Definition: HttpServerUtil.qm.dox.h:78
static staticPersistenceCleanup()
removes the thread-local data key in case the object is destroyed in another thread ...
constructor(*AbstractAuthenticator auth)
create the object optionally with the given AbstractAuthenticator
*hash authenticateRequest(HttpListenerInterface listener, hash hdr, reference cx)
primary method called to authenticate each request
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...
HttpListenerInterface listener
an HttpListenerInterface object for the listener serving the request for logging purposes ...
Definition: HttpServerUtil.qm.dox.h:359
static binary encodeBody(string ce, data body)
encodes a message body with content-encoding
static *string getLogMessage(hash cx, hash api, reference params, *reference args)
helper method for handling log messages
this abstract class defines the interface for classes that provide logging methods ...
Definition: HttpServerUtil.qm.dox.h:227
abstract addUserThreadContext(hash uctx)
adds user-defined data to be returned in the &quot;uctx&quot; context key when serving requests from this liste...
const DefaultTimeout
default timeout in ms
Definition: HttpServerUtil.qm.dox.h:84
private any send()
this is the primary callback for sending chunked responses; first sendImpl() is called to get the raw...
abstract class that all HTTP dedicated socket handler objects must inherit from
Definition: HttpServerUtil.qm.dox.h:650
abstract class for HTTP request handlers anchored at a specific URL
Definition: HttpServerUtil.qm.dox.h:626
static data decodeBody(string ce, binary body, *string enc)
decodes a message body with content-encoding
hash handleRequest(hash cx, hash hdr, *data body)
will be called when a request is received that should be directed to the handler
const LP_LEVELMASK
mask for the log level
Definition: HttpServerUtil.qm.dox.h:199
private hash getResponseHeaderMessage()
this method returns the response message description hash by calling getResponseHeaderMessageImpl() ...
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:81
timeout timeout_ms
send and receive socket timeout in milliseconds
Definition: HttpServerUtil.qm.dox.h:489
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:483
hash handleRequest()
handles the request
authenticate(string user, string pass="")
called to authenticate a user for a connection
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:492
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 ...
private AbstractStreamRequest getStreamRequestImpl(HttpListenerInterface listener, Socket s, hash cx, hash hdr, *data body)
returns the AbstractStreamRequest object for handling chunked requests
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
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: HttpServerUtil.qm.dox.h:631
nothing persistentClosed()
called externally when a persistent connection is closed
static hash redirect(hash cx, hash hdr, string path)
generates a redirect hash for the given path
const PersistenceThreadKey
thread-local key string for the persistent flag
Definition: HttpServerUtil.qm.dox.h:495
hash lsh
hash of listener stop flags
Definition: HttpServerUtil.qm.dox.h:661
any body
any message body given in a non-chunked request; could already be deserialized
Definition: HttpServerUtil.qm.dox.h:369
bool isPersistent()
returns True if the current connection is persistent, False if not
private nothing checkPersistent(hash cx, hash hdr)
this method will throw an exception if a persistent connection cannot be granted